@iqai/adk 0.1.0 → 0.1.2
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 +13 -0
- package/README.md +62 -0
- package/dist/index.d.mts +457 -93
- package/dist/index.d.ts +457 -93
- package/dist/index.js +1666 -1245
- package/dist/index.mjs +1657 -1236
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -594,6 +594,7 @@ You could retry calling this tool, but it is IMPORTANT for you to provide all th
|
|
|
594
594
|
var agents_exports = {};
|
|
595
595
|
__export(agents_exports, {
|
|
596
596
|
Agent: () => LlmAgent,
|
|
597
|
+
AgentBuilder: () => AgentBuilder,
|
|
597
598
|
BaseAgent: () => BaseAgent,
|
|
598
599
|
CallbackContext: () => CallbackContext,
|
|
599
600
|
InvocationContext: () => InvocationContext,
|
|
@@ -3475,9 +3476,21 @@ __export(tools_exports, {
|
|
|
3475
3476
|
HttpRequestTool: () => HttpRequestTool,
|
|
3476
3477
|
LoadArtifactsTool: () => LoadArtifactsTool,
|
|
3477
3478
|
LoadMemoryTool: () => LoadMemoryTool,
|
|
3479
|
+
McpAbi: () => McpAbi,
|
|
3480
|
+
McpAtp: () => McpAtp,
|
|
3481
|
+
McpBamm: () => McpBamm,
|
|
3478
3482
|
McpError: () => McpError,
|
|
3479
3483
|
McpErrorType: () => McpErrorType,
|
|
3484
|
+
McpFilesystem: () => McpFilesystem,
|
|
3485
|
+
McpFraxlend: () => McpFraxlend,
|
|
3486
|
+
McpGeneric: () => McpGeneric,
|
|
3487
|
+
McpIqWiki: () => McpIqWiki,
|
|
3488
|
+
McpMemory: () => McpMemory,
|
|
3489
|
+
McpNearAgent: () => McpNearAgent,
|
|
3490
|
+
McpNearIntentSwaps: () => McpNearIntentSwaps,
|
|
3491
|
+
McpOdos: () => McpOdos,
|
|
3480
3492
|
McpSamplingHandler: () => McpSamplingHandler,
|
|
3493
|
+
McpTelegram: () => McpTelegram,
|
|
3481
3494
|
McpToolset: () => McpToolset,
|
|
3482
3495
|
ToolContext: () => ToolContext,
|
|
3483
3496
|
TransferToAgentTool: () => TransferToAgentTool,
|
|
@@ -4420,9 +4433,9 @@ var McpSamplingHandler = class {
|
|
|
4420
4433
|
mcpParams.messages,
|
|
4421
4434
|
mcpParams.systemPrompt
|
|
4422
4435
|
);
|
|
4436
|
+
const requestModel = mcpParams.model || "gemini-2.0-flash";
|
|
4423
4437
|
const adkRequest = new LlmRequest({
|
|
4424
|
-
model:
|
|
4425
|
-
// TODO: Implement model passing from context
|
|
4438
|
+
model: requestModel,
|
|
4426
4439
|
contents: adkContents,
|
|
4427
4440
|
config: {
|
|
4428
4441
|
temperature: mcpParams.temperature,
|
|
@@ -4432,7 +4445,10 @@ var McpSamplingHandler = class {
|
|
|
4432
4445
|
this.logger.debug("Calling ADK sampling handler");
|
|
4433
4446
|
const adkResponse = await this.samplingHandler(adkRequest);
|
|
4434
4447
|
this.logger.debug("Converting ADK response to MCP format");
|
|
4435
|
-
const mcpResponse = this.convertADKResponseToMcp(
|
|
4448
|
+
const mcpResponse = this.convertADKResponseToMcp(
|
|
4449
|
+
adkResponse,
|
|
4450
|
+
requestModel
|
|
4451
|
+
);
|
|
4436
4452
|
const responseValidation = CreateMessageResultSchema.safeParse(mcpResponse);
|
|
4437
4453
|
if (!responseValidation.success) {
|
|
4438
4454
|
this.logger.error(
|
|
@@ -4521,7 +4537,7 @@ var McpSamplingHandler = class {
|
|
|
4521
4537
|
/**
|
|
4522
4538
|
* Convert ADK response to MCP response format
|
|
4523
4539
|
*/
|
|
4524
|
-
convertADKResponseToMcp(adkResponse) {
|
|
4540
|
+
convertADKResponseToMcp(adkResponse, model) {
|
|
4525
4541
|
let responseText = "";
|
|
4526
4542
|
if (adkResponse.content) {
|
|
4527
4543
|
if (typeof adkResponse.content === "string") {
|
|
@@ -4533,6 +4549,8 @@ var McpSamplingHandler = class {
|
|
|
4533
4549
|
}
|
|
4534
4550
|
}
|
|
4535
4551
|
const mcpResponse = {
|
|
4552
|
+
model,
|
|
4553
|
+
// Use the model from the request
|
|
4536
4554
|
role: "assistant",
|
|
4537
4555
|
// ADK responses are always from assistant
|
|
4538
4556
|
content: {
|
|
@@ -4807,28 +4825,40 @@ var McpClientService = class {
|
|
|
4807
4825
|
}
|
|
4808
4826
|
return;
|
|
4809
4827
|
}
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4828
|
+
try {
|
|
4829
|
+
client.setRequestHandler(
|
|
4830
|
+
CreateMessageRequestSchema2,
|
|
4831
|
+
async (request) => {
|
|
4832
|
+
try {
|
|
4833
|
+
this.logger.debug("Received sampling request:", request);
|
|
4834
|
+
const response = await this.mcpSamplingHandler.handleSamplingRequest(request);
|
|
4835
|
+
if (this.config.debug) {
|
|
4836
|
+
console.log("\u2705 Sampling request completed successfully");
|
|
4837
|
+
}
|
|
4838
|
+
return response;
|
|
4839
|
+
} catch (error) {
|
|
4840
|
+
console.error("\u274C Error handling sampling request:", error);
|
|
4841
|
+
if (error instanceof McpError) {
|
|
4842
|
+
throw error;
|
|
4843
|
+
}
|
|
4844
|
+
throw new McpError(
|
|
4845
|
+
`Sampling request failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
4846
|
+
"SAMPLING_ERROR" /* SAMPLING_ERROR */,
|
|
4847
|
+
error instanceof Error ? error : void 0
|
|
4848
|
+
);
|
|
4849
|
+
}
|
|
4822
4850
|
}
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4851
|
+
);
|
|
4852
|
+
if (this.config.debug) {
|
|
4853
|
+
console.log("\u{1F3AF} Sampling handler registered successfully");
|
|
4854
|
+
}
|
|
4855
|
+
} catch (error) {
|
|
4856
|
+
console.error("Failed to setup sampling handler:", error);
|
|
4857
|
+
if (this.config.debug) {
|
|
4858
|
+
console.log(
|
|
4859
|
+
"\u26A0\uFE0F Sampling handler registration failed, continuing without sampling support"
|
|
4827
4860
|
);
|
|
4828
4861
|
}
|
|
4829
|
-
});
|
|
4830
|
-
if (this.config.debug) {
|
|
4831
|
-
console.log("\u{1F3AF} Sampling handler registered successfully");
|
|
4832
4862
|
}
|
|
4833
4863
|
}
|
|
4834
4864
|
/**
|
|
@@ -5145,6 +5175,117 @@ var McpToolAdapter = class extends BaseTool {
|
|
|
5145
5175
|
}
|
|
5146
5176
|
};
|
|
5147
5177
|
|
|
5178
|
+
// src/tools/mcp/servers.ts
|
|
5179
|
+
function createMcpConfig(name, packageName, config) {
|
|
5180
|
+
const { debug, description, retryOptions, env: envVars = {} } = config;
|
|
5181
|
+
const env = {};
|
|
5182
|
+
for (const [key, value] of Object.entries(envVars)) {
|
|
5183
|
+
if (value !== void 0) {
|
|
5184
|
+
env[key] = String(value);
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
if (!env.PATH) {
|
|
5188
|
+
env.PATH = process.env.PATH || "";
|
|
5189
|
+
}
|
|
5190
|
+
return {
|
|
5191
|
+
name,
|
|
5192
|
+
description: description || `Client for ${name}`,
|
|
5193
|
+
debug: debug || false,
|
|
5194
|
+
retryOptions: retryOptions || { maxRetries: 2, initialDelay: 200 },
|
|
5195
|
+
transport: {
|
|
5196
|
+
mode: "stdio",
|
|
5197
|
+
command: "npx",
|
|
5198
|
+
args: ["-y", packageName],
|
|
5199
|
+
env
|
|
5200
|
+
}
|
|
5201
|
+
};
|
|
5202
|
+
}
|
|
5203
|
+
function McpAbi(config) {
|
|
5204
|
+
const mcpConfig = createMcpConfig("ABI MCP Client", "@iqai/mcp-abi", config);
|
|
5205
|
+
return new McpToolset(mcpConfig);
|
|
5206
|
+
}
|
|
5207
|
+
function McpAtp(config) {
|
|
5208
|
+
const mcpConfig = createMcpConfig("ATP MCP Client", "@iqai/mcp-atp", config);
|
|
5209
|
+
return new McpToolset(mcpConfig);
|
|
5210
|
+
}
|
|
5211
|
+
function McpBamm(config) {
|
|
5212
|
+
const mcpConfig = createMcpConfig(
|
|
5213
|
+
"BAMM MCP Client",
|
|
5214
|
+
"@iqai/mcp-bamm",
|
|
5215
|
+
config
|
|
5216
|
+
);
|
|
5217
|
+
return new McpToolset(mcpConfig);
|
|
5218
|
+
}
|
|
5219
|
+
function McpFraxlend(config) {
|
|
5220
|
+
const mcpConfig = createMcpConfig(
|
|
5221
|
+
"Fraxlend MCP Client",
|
|
5222
|
+
"@iqai/mcp-fraxlend",
|
|
5223
|
+
config
|
|
5224
|
+
);
|
|
5225
|
+
return new McpToolset(mcpConfig);
|
|
5226
|
+
}
|
|
5227
|
+
function McpIqWiki(config = {}) {
|
|
5228
|
+
const mcpConfig = createMcpConfig(
|
|
5229
|
+
"IQWiki MCP Client",
|
|
5230
|
+
"@iqai/mcp-iqwiki",
|
|
5231
|
+
config
|
|
5232
|
+
);
|
|
5233
|
+
return new McpToolset(mcpConfig);
|
|
5234
|
+
}
|
|
5235
|
+
function McpNearAgent(config) {
|
|
5236
|
+
const mcpConfig = createMcpConfig(
|
|
5237
|
+
"NEAR Agent MCP Client",
|
|
5238
|
+
"@iqai/mcp-near-agent",
|
|
5239
|
+
config
|
|
5240
|
+
);
|
|
5241
|
+
return new McpToolset(mcpConfig);
|
|
5242
|
+
}
|
|
5243
|
+
function McpNearIntentSwaps(config) {
|
|
5244
|
+
const mcpConfig = createMcpConfig(
|
|
5245
|
+
"NEAR Intent Swaps MCP Client",
|
|
5246
|
+
"@iqai/mcp-near-intent-swaps",
|
|
5247
|
+
config
|
|
5248
|
+
);
|
|
5249
|
+
return new McpToolset(mcpConfig);
|
|
5250
|
+
}
|
|
5251
|
+
function McpOdos(config) {
|
|
5252
|
+
const mcpConfig = createMcpConfig(
|
|
5253
|
+
"ODOS MCP Client",
|
|
5254
|
+
"@iqai/mcp-odos",
|
|
5255
|
+
config
|
|
5256
|
+
);
|
|
5257
|
+
return new McpToolset(mcpConfig);
|
|
5258
|
+
}
|
|
5259
|
+
function McpTelegram(config) {
|
|
5260
|
+
const mcpConfig = createMcpConfig(
|
|
5261
|
+
"Telegram MCP Client",
|
|
5262
|
+
"@iqai/mcp-telegram",
|
|
5263
|
+
config
|
|
5264
|
+
);
|
|
5265
|
+
return new McpToolset(mcpConfig);
|
|
5266
|
+
}
|
|
5267
|
+
function McpFilesystem(config = {}) {
|
|
5268
|
+
const mcpConfig = createMcpConfig(
|
|
5269
|
+
"Filesystem MCP Client",
|
|
5270
|
+
"@modelcontextprotocol/server-filesystem",
|
|
5271
|
+
config
|
|
5272
|
+
);
|
|
5273
|
+
return new McpToolset(mcpConfig);
|
|
5274
|
+
}
|
|
5275
|
+
function McpMemory(config = {}) {
|
|
5276
|
+
const mcpConfig = createMcpConfig(
|
|
5277
|
+
"Memory MCP Client",
|
|
5278
|
+
"@modelcontextprotocol/server-memory",
|
|
5279
|
+
config
|
|
5280
|
+
);
|
|
5281
|
+
return new McpToolset(mcpConfig);
|
|
5282
|
+
}
|
|
5283
|
+
function McpGeneric(packageName, config = {}, name) {
|
|
5284
|
+
const clientName = name || `${packageName} Client`;
|
|
5285
|
+
const mcpConfig = createMcpConfig(clientName, packageName, config);
|
|
5286
|
+
return new McpToolset(mcpConfig);
|
|
5287
|
+
}
|
|
5288
|
+
|
|
5148
5289
|
// src/tools/mcp/index.ts
|
|
5149
5290
|
var McpToolset = class {
|
|
5150
5291
|
config;
|
|
@@ -8092,6 +8233,9 @@ var LangGraphAgent = class extends BaseAgent {
|
|
|
8092
8233
|
}
|
|
8093
8234
|
};
|
|
8094
8235
|
|
|
8236
|
+
// src/runners.ts
|
|
8237
|
+
import { SpanStatusCode } from "@opentelemetry/api";
|
|
8238
|
+
|
|
8095
8239
|
// src/agents/run-config.ts
|
|
8096
8240
|
var StreamingMode = /* @__PURE__ */ ((StreamingMode2) => {
|
|
8097
8241
|
StreamingMode2["NONE"] = "NONE";
|
|
@@ -8186,11 +8330,87 @@ var RunConfig = class {
|
|
|
8186
8330
|
}
|
|
8187
8331
|
};
|
|
8188
8332
|
|
|
8189
|
-
// src/memory
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8333
|
+
// src/artifacts/in-memory-artifact-service.ts
|
|
8334
|
+
init_logger();
|
|
8335
|
+
var logger9 = new Logger({ name: "InMemoryArtifactService" });
|
|
8336
|
+
var InMemoryArtifactService = class {
|
|
8337
|
+
artifacts = /* @__PURE__ */ new Map();
|
|
8338
|
+
fileHasUserNamespace(filename) {
|
|
8339
|
+
return filename.startsWith("user:");
|
|
8340
|
+
}
|
|
8341
|
+
getArtifactPath(appName, userId, sessionId, filename) {
|
|
8342
|
+
if (this.fileHasUserNamespace(filename)) {
|
|
8343
|
+
return `${appName}/${userId}/user/${filename}`;
|
|
8344
|
+
}
|
|
8345
|
+
return `${appName}/${userId}/${sessionId}/${filename}`;
|
|
8346
|
+
}
|
|
8347
|
+
async saveArtifact(args) {
|
|
8348
|
+
const { appName, userId, sessionId, filename, artifact } = args;
|
|
8349
|
+
const path2 = this.getArtifactPath(appName, userId, sessionId, filename);
|
|
8350
|
+
if (!this.artifacts.has(path2)) {
|
|
8351
|
+
this.artifacts.set(path2, []);
|
|
8352
|
+
}
|
|
8353
|
+
const versions = this.artifacts.get(path2);
|
|
8354
|
+
const version = versions.length;
|
|
8355
|
+
versions.push(artifact);
|
|
8356
|
+
return version;
|
|
8357
|
+
}
|
|
8358
|
+
async loadArtifact(args) {
|
|
8359
|
+
const { appName, userId, sessionId, filename, version } = args;
|
|
8360
|
+
const path2 = this.getArtifactPath(appName, userId, sessionId, filename);
|
|
8361
|
+
const versions = this.artifacts.get(path2);
|
|
8362
|
+
if (!versions || versions.length === 0) {
|
|
8363
|
+
return null;
|
|
8364
|
+
}
|
|
8365
|
+
let targetVersion = version;
|
|
8366
|
+
if (targetVersion === void 0 || targetVersion === null) {
|
|
8367
|
+
targetVersion = versions.length - 1;
|
|
8368
|
+
}
|
|
8369
|
+
if (targetVersion < 0) {
|
|
8370
|
+
targetVersion = versions.length + targetVersion;
|
|
8371
|
+
}
|
|
8372
|
+
if (targetVersion < 0 || targetVersion >= versions.length) {
|
|
8373
|
+
return null;
|
|
8374
|
+
}
|
|
8375
|
+
return versions[targetVersion];
|
|
8376
|
+
}
|
|
8377
|
+
async listArtifactKeys(args) {
|
|
8378
|
+
const { appName, userId, sessionId } = args;
|
|
8379
|
+
const sessionPrefix = `${appName}/${userId}/${sessionId}/`;
|
|
8380
|
+
const userNamespacePrefix = `${appName}/${userId}/user/`;
|
|
8381
|
+
const filenames = [];
|
|
8382
|
+
for (const path2 of this.artifacts.keys()) {
|
|
8383
|
+
if (path2.startsWith(sessionPrefix)) {
|
|
8384
|
+
const filename = path2.substring(sessionPrefix.length);
|
|
8385
|
+
filenames.push(filename);
|
|
8386
|
+
} else if (path2.startsWith(userNamespacePrefix)) {
|
|
8387
|
+
const filename = path2.substring(userNamespacePrefix.length);
|
|
8388
|
+
filenames.push(filename);
|
|
8389
|
+
}
|
|
8390
|
+
}
|
|
8391
|
+
return filenames.sort();
|
|
8392
|
+
}
|
|
8393
|
+
async deleteArtifact(args) {
|
|
8394
|
+
const { appName, userId, sessionId, filename } = args;
|
|
8395
|
+
const path2 = this.getArtifactPath(appName, userId, sessionId, filename);
|
|
8396
|
+
if (!this.artifacts.has(path2)) {
|
|
8397
|
+
return;
|
|
8398
|
+
}
|
|
8399
|
+
this.artifacts.delete(path2);
|
|
8400
|
+
}
|
|
8401
|
+
async listVersions(args) {
|
|
8402
|
+
const { appName, userId, sessionId, filename } = args;
|
|
8403
|
+
const path2 = this.getArtifactPath(appName, userId, sessionId, filename);
|
|
8404
|
+
const versions = this.artifacts.get(path2);
|
|
8405
|
+
if (!versions || versions.length === 0) {
|
|
8406
|
+
return [];
|
|
8407
|
+
}
|
|
8408
|
+
return Array.from({ length: versions.length }, (_, i) => i);
|
|
8409
|
+
}
|
|
8410
|
+
};
|
|
8411
|
+
|
|
8412
|
+
// src/runners.ts
|
|
8413
|
+
init_logger();
|
|
8194
8414
|
|
|
8195
8415
|
// src/memory/_utils.ts
|
|
8196
8416
|
function formatTimestamp(timestamp) {
|
|
@@ -8308,19 +8528,8 @@ var InMemoryMemoryService = class {
|
|
|
8308
8528
|
}
|
|
8309
8529
|
};
|
|
8310
8530
|
|
|
8311
|
-
// src/sessions/
|
|
8312
|
-
|
|
8313
|
-
__export(sessions_exports, {
|
|
8314
|
-
BaseSessionService: () => BaseSessionService,
|
|
8315
|
-
DatabaseSessionService: () => DatabaseSessionService,
|
|
8316
|
-
InMemorySessionService: () => InMemorySessionService,
|
|
8317
|
-
State: () => State,
|
|
8318
|
-
VertexAiSessionService: () => VertexAiSessionService,
|
|
8319
|
-
createDatabaseSessionService: () => createDatabaseSessionService,
|
|
8320
|
-
createMysqlSessionService: () => createMysqlSessionService,
|
|
8321
|
-
createPostgresSessionService: () => createPostgresSessionService,
|
|
8322
|
-
createSqliteSessionService: () => createSqliteSessionService
|
|
8323
|
-
});
|
|
8531
|
+
// src/sessions/in-memory-session-service.ts
|
|
8532
|
+
import { randomUUID } from "crypto";
|
|
8324
8533
|
|
|
8325
8534
|
// src/sessions/base-session-service.ts
|
|
8326
8535
|
var BaseSessionService = class {
|
|
@@ -8359,7 +8568,6 @@ var BaseSessionService = class {
|
|
|
8359
8568
|
};
|
|
8360
8569
|
|
|
8361
8570
|
// src/sessions/in-memory-session-service.ts
|
|
8362
|
-
import { randomUUID } from "crypto";
|
|
8363
8571
|
var InMemorySessionService = class extends BaseSessionService {
|
|
8364
8572
|
/**
|
|
8365
8573
|
* A map from app name to a map from user ID to a map from session ID to session.
|
|
@@ -8571,1340 +8779,1541 @@ var InMemorySessionService = class extends BaseSessionService {
|
|
|
8571
8779
|
}
|
|
8572
8780
|
};
|
|
8573
8781
|
|
|
8574
|
-
// src/
|
|
8575
|
-
var
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
* Initializes the VertexAiSessionService.
|
|
8581
|
-
*/
|
|
8582
|
-
constructor(options = {}) {
|
|
8583
|
-
super();
|
|
8584
|
-
this.project = options.project;
|
|
8585
|
-
this.location = options.location;
|
|
8586
|
-
this.agentEngineId = options.agentEngineId;
|
|
8782
|
+
// src/runners.ts
|
|
8783
|
+
var logger10 = new Logger({ name: "Runner" });
|
|
8784
|
+
function _findFunctionCallEventIfLastEventIsFunctionResponse(session) {
|
|
8785
|
+
const events = session.events;
|
|
8786
|
+
if (!events || events.length === 0) {
|
|
8787
|
+
return null;
|
|
8587
8788
|
}
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
http_method: "POST",
|
|
8602
|
-
path: `reasoningEngines/${reasoningEngineId}/sessions`,
|
|
8603
|
-
request_dict: sessionJsonDict
|
|
8604
|
-
});
|
|
8605
|
-
console.info("Create Session response", apiResponse);
|
|
8606
|
-
const createdSessionId = apiResponse.name.split("/").slice(-3, -2)[0];
|
|
8607
|
-
const operationId = apiResponse.name.split("/").pop();
|
|
8608
|
-
let maxRetryAttempt = 5;
|
|
8609
|
-
let lroResponse = null;
|
|
8610
|
-
while (maxRetryAttempt >= 0) {
|
|
8611
|
-
lroResponse = await apiClient.async_request({
|
|
8612
|
-
http_method: "GET",
|
|
8613
|
-
path: `operations/${operationId}`,
|
|
8614
|
-
request_dict: {}
|
|
8615
|
-
});
|
|
8616
|
-
if (lroResponse?.done) {
|
|
8617
|
-
break;
|
|
8789
|
+
const lastEvent = events[events.length - 1];
|
|
8790
|
+
if (lastEvent.content?.parts?.some((part) => part.functionResponse)) {
|
|
8791
|
+
const functionCallId = lastEvent.content.parts.find(
|
|
8792
|
+
(part) => part.functionResponse
|
|
8793
|
+
)?.functionResponse?.id;
|
|
8794
|
+
if (!functionCallId) return null;
|
|
8795
|
+
for (let i = events.length - 2; i >= 0; i--) {
|
|
8796
|
+
const event = events[i];
|
|
8797
|
+
const functionCalls = event.getFunctionCalls?.() || [];
|
|
8798
|
+
for (const functionCall of functionCalls) {
|
|
8799
|
+
if (functionCall.id === functionCallId) {
|
|
8800
|
+
return event;
|
|
8801
|
+
}
|
|
8618
8802
|
}
|
|
8619
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
8620
|
-
maxRetryAttempt--;
|
|
8621
|
-
}
|
|
8622
|
-
if (!lroResponse || !lroResponse.done) {
|
|
8623
|
-
throw new Error(
|
|
8624
|
-
`Timeout waiting for operation ${operationId} to complete.`
|
|
8625
|
-
);
|
|
8626
8803
|
}
|
|
8627
|
-
const getSessionApiResponse = await apiClient.async_request({
|
|
8628
|
-
http_method: "GET",
|
|
8629
|
-
path: `reasoningEngines/${reasoningEngineId}/sessions/${createdSessionId}`,
|
|
8630
|
-
request_dict: {}
|
|
8631
|
-
});
|
|
8632
|
-
const updateTimestamp = new Date(getSessionApiResponse.updateTime).getTime() / 1e3;
|
|
8633
|
-
return {
|
|
8634
|
-
appName: String(appName),
|
|
8635
|
-
userId: String(userId),
|
|
8636
|
-
id: String(createdSessionId),
|
|
8637
|
-
state: getSessionApiResponse.sessionState || {},
|
|
8638
|
-
events: [],
|
|
8639
|
-
lastUpdateTime: updateTimestamp
|
|
8640
|
-
};
|
|
8641
8804
|
}
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8663
|
-
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8805
|
+
return null;
|
|
8806
|
+
}
|
|
8807
|
+
var Runner = class {
|
|
8808
|
+
/**
|
|
8809
|
+
* The app name of the runner.
|
|
8810
|
+
*/
|
|
8811
|
+
appName;
|
|
8812
|
+
/**
|
|
8813
|
+
* The root agent to run.
|
|
8814
|
+
*/
|
|
8815
|
+
agent;
|
|
8816
|
+
/**
|
|
8817
|
+
* The artifact service for the runner.
|
|
8818
|
+
*/
|
|
8819
|
+
artifactService;
|
|
8820
|
+
/**
|
|
8821
|
+
* The session service for the runner.
|
|
8822
|
+
*/
|
|
8823
|
+
sessionService;
|
|
8824
|
+
/**
|
|
8825
|
+
* The memory service for the runner.
|
|
8826
|
+
*/
|
|
8827
|
+
memoryService;
|
|
8828
|
+
/**
|
|
8829
|
+
* Initializes the Runner.
|
|
8830
|
+
*/
|
|
8831
|
+
constructor({
|
|
8832
|
+
appName,
|
|
8833
|
+
agent,
|
|
8834
|
+
artifactService,
|
|
8835
|
+
sessionService,
|
|
8836
|
+
memoryService
|
|
8837
|
+
}) {
|
|
8838
|
+
this.appName = appName;
|
|
8839
|
+
this.agent = agent;
|
|
8840
|
+
this.artifactService = artifactService;
|
|
8841
|
+
this.sessionService = sessionService;
|
|
8842
|
+
this.memoryService = memoryService;
|
|
8843
|
+
}
|
|
8844
|
+
/**
|
|
8845
|
+
* Runs the agent synchronously.
|
|
8846
|
+
* NOTE: This sync interface is only for local testing and convenience purpose.
|
|
8847
|
+
* Consider using `runAsync` for production usage.
|
|
8848
|
+
*/
|
|
8849
|
+
run({
|
|
8850
|
+
userId,
|
|
8851
|
+
sessionId,
|
|
8852
|
+
newMessage,
|
|
8853
|
+
runConfig = new RunConfig()
|
|
8854
|
+
}) {
|
|
8855
|
+
const eventQueue = [];
|
|
8856
|
+
let queueIndex = 0;
|
|
8857
|
+
let asyncCompleted = false;
|
|
8858
|
+
const invokeRunAsync = async () => {
|
|
8859
|
+
try {
|
|
8860
|
+
for await (const event of this.runAsync({
|
|
8861
|
+
userId,
|
|
8862
|
+
sessionId,
|
|
8863
|
+
newMessage,
|
|
8864
|
+
runConfig
|
|
8865
|
+
})) {
|
|
8866
|
+
eventQueue.push(event);
|
|
8867
|
+
}
|
|
8868
|
+
} finally {
|
|
8869
|
+
eventQueue.push(null);
|
|
8870
|
+
asyncCompleted = true;
|
|
8673
8871
|
}
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8872
|
+
};
|
|
8873
|
+
invokeRunAsync();
|
|
8874
|
+
return function* () {
|
|
8875
|
+
while (true) {
|
|
8876
|
+
while (queueIndex >= eventQueue.length && !asyncCompleted) {
|
|
8877
|
+
}
|
|
8878
|
+
if (queueIndex >= eventQueue.length && asyncCompleted) {
|
|
8879
|
+
break;
|
|
8880
|
+
}
|
|
8881
|
+
const event = eventQueue[queueIndex++];
|
|
8882
|
+
if (event === null) {
|
|
8883
|
+
break;
|
|
8685
8884
|
}
|
|
8885
|
+
yield event;
|
|
8686
8886
|
}
|
|
8687
|
-
|
|
8688
|
-
|
|
8887
|
+
}();
|
|
8888
|
+
}
|
|
8889
|
+
/**
|
|
8890
|
+
* Main entry method to run the agent in this runner.
|
|
8891
|
+
*/
|
|
8892
|
+
async *runAsync({
|
|
8893
|
+
userId,
|
|
8894
|
+
sessionId,
|
|
8895
|
+
newMessage,
|
|
8896
|
+
runConfig = new RunConfig()
|
|
8897
|
+
}) {
|
|
8898
|
+
const span = tracer.startSpan("invocation");
|
|
8899
|
+
try {
|
|
8900
|
+
const session = await this.sessionService.getSession(
|
|
8901
|
+
this.appName,
|
|
8902
|
+
userId,
|
|
8903
|
+
sessionId
|
|
8689
8904
|
);
|
|
8690
|
-
session
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8905
|
+
if (!session) {
|
|
8906
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
8907
|
+
}
|
|
8908
|
+
const invocationContext = this._newInvocationContext(session, {
|
|
8909
|
+
newMessage,
|
|
8910
|
+
runConfig
|
|
8911
|
+
});
|
|
8912
|
+
if (newMessage) {
|
|
8913
|
+
await this._appendNewMessageToSession(
|
|
8914
|
+
session,
|
|
8915
|
+
newMessage,
|
|
8916
|
+
invocationContext,
|
|
8917
|
+
runConfig.saveInputBlobsAsArtifacts || false
|
|
8918
|
+
);
|
|
8919
|
+
}
|
|
8920
|
+
invocationContext.agent = this._findAgentToRun(session, this.agent);
|
|
8921
|
+
for await (const event of invocationContext.agent.runAsync(
|
|
8922
|
+
invocationContext
|
|
8923
|
+
)) {
|
|
8924
|
+
if (!event.partial) {
|
|
8925
|
+
await this.sessionService.appendEvent(session, event);
|
|
8705
8926
|
}
|
|
8927
|
+
yield event;
|
|
8706
8928
|
}
|
|
8707
|
-
return session;
|
|
8708
8929
|
} catch (error) {
|
|
8709
|
-
|
|
8710
|
-
|
|
8930
|
+
logger10.debug("Error running agent:", error);
|
|
8931
|
+
span.recordException(error);
|
|
8932
|
+
span.setStatus({
|
|
8933
|
+
code: SpanStatusCode.ERROR,
|
|
8934
|
+
message: error instanceof Error ? error.message : "Unknown error"
|
|
8935
|
+
});
|
|
8936
|
+
throw error;
|
|
8937
|
+
} finally {
|
|
8938
|
+
span.end();
|
|
8711
8939
|
}
|
|
8712
8940
|
}
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
|
|
8717
|
-
if (
|
|
8718
|
-
|
|
8719
|
-
path2 = `${path2}?filter=user_id=${parsedUserId}`;
|
|
8720
|
-
}
|
|
8721
|
-
const apiResponse = await apiClient.async_request({
|
|
8722
|
-
http_method: "GET",
|
|
8723
|
-
path: path2,
|
|
8724
|
-
request_dict: {}
|
|
8725
|
-
});
|
|
8726
|
-
if (apiResponse.httpHeaders) {
|
|
8727
|
-
return { sessions: [] };
|
|
8941
|
+
/**
|
|
8942
|
+
* Appends a new message to the session.
|
|
8943
|
+
*/
|
|
8944
|
+
async _appendNewMessageToSession(session, newMessage, invocationContext, saveInputBlobsAsArtifacts = false) {
|
|
8945
|
+
if (!newMessage.parts) {
|
|
8946
|
+
throw new Error("No parts in the new_message.");
|
|
8728
8947
|
}
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8948
|
+
if (this.artifactService && saveInputBlobsAsArtifacts) {
|
|
8949
|
+
for (let i = 0; i < newMessage.parts.length; i++) {
|
|
8950
|
+
const part = newMessage.parts[i];
|
|
8951
|
+
if (!part.inlineData) {
|
|
8952
|
+
continue;
|
|
8953
|
+
}
|
|
8954
|
+
const fileName = `artifact_${invocationContext.invocationId}_${i}`;
|
|
8955
|
+
await this.artifactService.saveArtifact({
|
|
8956
|
+
appName: this.appName,
|
|
8957
|
+
userId: session.userId,
|
|
8958
|
+
sessionId: session.id,
|
|
8959
|
+
filename: fileName,
|
|
8960
|
+
artifact: part
|
|
8961
|
+
});
|
|
8962
|
+
newMessage.parts[i] = {
|
|
8963
|
+
text: `Uploaded file: ${fileName}. It is saved into artifacts`
|
|
8739
8964
|
};
|
|
8740
|
-
sessions.push(session);
|
|
8741
8965
|
}
|
|
8742
8966
|
}
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
request_dict: {}
|
|
8753
|
-
});
|
|
8754
|
-
} catch (error) {
|
|
8755
|
-
console.error(`Error deleting session ${sessionId}:`, error);
|
|
8756
|
-
throw error;
|
|
8757
|
-
}
|
|
8758
|
-
}
|
|
8759
|
-
async appendEvent(session, event) {
|
|
8760
|
-
await super.appendEvent(session, event);
|
|
8761
|
-
const reasoningEngineId = this.getReasoningEngineId(session.appName);
|
|
8762
|
-
const apiClient = this.getApiClient();
|
|
8763
|
-
await apiClient.async_request({
|
|
8764
|
-
http_method: "POST",
|
|
8765
|
-
path: `reasoningEngines/${reasoningEngineId}/sessions/${session.id}:appendEvent`,
|
|
8766
|
-
request_dict: this.convertEventToJson(event)
|
|
8967
|
+
const userContent = {
|
|
8968
|
+
...newMessage,
|
|
8969
|
+
role: "user"
|
|
8970
|
+
// Ensure role is set for content filtering
|
|
8971
|
+
};
|
|
8972
|
+
const event = new Event({
|
|
8973
|
+
invocationId: invocationContext.invocationId,
|
|
8974
|
+
author: "user",
|
|
8975
|
+
content: userContent
|
|
8767
8976
|
});
|
|
8768
|
-
|
|
8977
|
+
await this.sessionService.appendEvent(session, event);
|
|
8769
8978
|
}
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8979
|
+
/**
|
|
8980
|
+
* Finds the agent to run to continue the session.
|
|
8981
|
+
*/
|
|
8982
|
+
_findAgentToRun(session, rootAgent) {
|
|
8983
|
+
const event = _findFunctionCallEventIfLastEventIsFunctionResponse(session);
|
|
8984
|
+
if (event?.author) {
|
|
8985
|
+
return rootAgent.findAgent(event.author);
|
|
8776
8986
|
}
|
|
8777
|
-
const
|
|
8778
|
-
const
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
);
|
|
8987
|
+
const nonUserEvents = session.events?.filter((e) => e.author !== "user").reverse() || [];
|
|
8988
|
+
for (const event2 of nonUserEvents) {
|
|
8989
|
+
if (event2.author === rootAgent.name) {
|
|
8990
|
+
return rootAgent;
|
|
8991
|
+
}
|
|
8992
|
+
const agent = rootAgent.findSubAgent?.(event2.author);
|
|
8993
|
+
if (!agent) {
|
|
8994
|
+
logger10.debug(
|
|
8995
|
+
`Event from an unknown agent: ${event2.author}, event id: ${event2.id}`
|
|
8996
|
+
);
|
|
8997
|
+
continue;
|
|
8998
|
+
}
|
|
8999
|
+
if (this._isTransferableAcrossAgentTree(agent)) {
|
|
9000
|
+
return agent;
|
|
9001
|
+
}
|
|
8783
9002
|
}
|
|
8784
|
-
return
|
|
8785
|
-
}
|
|
8786
|
-
getApiClient() {
|
|
8787
|
-
const { GoogleGenAI: GoogleGenAI2 } = __require("@google/genai");
|
|
8788
|
-
const client = new GoogleGenAI2({
|
|
8789
|
-
vertexai: true,
|
|
8790
|
-
project: this.project,
|
|
8791
|
-
location: this.location
|
|
8792
|
-
});
|
|
8793
|
-
return client._api_client;
|
|
9003
|
+
return rootAgent;
|
|
8794
9004
|
}
|
|
8795
|
-
|
|
8796
|
-
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
invocation_id: event.invocationId,
|
|
8809
|
-
timestamp: {
|
|
8810
|
-
seconds: Math.floor(event.timestamp),
|
|
8811
|
-
nanos: Math.floor(
|
|
8812
|
-
(event.timestamp - Math.floor(event.timestamp)) * 1e9
|
|
8813
|
-
)
|
|
8814
|
-
},
|
|
8815
|
-
error_code: event.errorCode,
|
|
8816
|
-
error_message: event.errorMessage,
|
|
8817
|
-
event_metadata: metadataJson
|
|
8818
|
-
};
|
|
8819
|
-
if (event.actions) {
|
|
8820
|
-
const actionsJson = {
|
|
8821
|
-
skip_summarization: event.actions.skipSummarization,
|
|
8822
|
-
state_delta: event.actions.stateDelta,
|
|
8823
|
-
artifact_delta: event.actions.artifactDelta,
|
|
8824
|
-
transfer_agent: event.actions.transferToAgent,
|
|
8825
|
-
escalate: event.actions.escalate,
|
|
8826
|
-
requested_auth_configs: event.actions.requestedAuthConfigs
|
|
8827
|
-
};
|
|
8828
|
-
eventJson.actions = actionsJson;
|
|
8829
|
-
}
|
|
8830
|
-
if (event.content) {
|
|
8831
|
-
eventJson.content = event.content;
|
|
9005
|
+
/**
|
|
9006
|
+
* Whether the agent to run can transfer to any other agent in the agent tree.
|
|
9007
|
+
*/
|
|
9008
|
+
_isTransferableAcrossAgentTree(agentToRun) {
|
|
9009
|
+
let agent = agentToRun;
|
|
9010
|
+
while (agent) {
|
|
9011
|
+
if (!(agent instanceof LlmAgent)) {
|
|
9012
|
+
return false;
|
|
9013
|
+
}
|
|
9014
|
+
if (agent.disallowTransferToParent) {
|
|
9015
|
+
return false;
|
|
9016
|
+
}
|
|
9017
|
+
agent = agent.parentAgent || null;
|
|
8832
9018
|
}
|
|
8833
|
-
return
|
|
9019
|
+
return true;
|
|
8834
9020
|
}
|
|
8835
|
-
|
|
8836
|
-
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8844
|
-
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
timestamp: new Date(apiEvent.timestamp).getTime() / 1e3
|
|
9021
|
+
/**
|
|
9022
|
+
* Creates a new invocation context.
|
|
9023
|
+
*/
|
|
9024
|
+
_newInvocationContext(session, {
|
|
9025
|
+
newMessage,
|
|
9026
|
+
runConfig = new RunConfig()
|
|
9027
|
+
}) {
|
|
9028
|
+
const invocationId = newInvocationContextId();
|
|
9029
|
+
return new InvocationContext({
|
|
9030
|
+
artifactService: this.artifactService,
|
|
9031
|
+
sessionService: this.sessionService,
|
|
9032
|
+
memoryService: this.memoryService,
|
|
9033
|
+
invocationId,
|
|
9034
|
+
agent: this.agent,
|
|
9035
|
+
session,
|
|
9036
|
+
userContent: newMessage || null,
|
|
9037
|
+
liveRequestQueue: null,
|
|
9038
|
+
runConfig
|
|
8854
9039
|
});
|
|
8855
|
-
if (apiEvent.errorCode) {
|
|
8856
|
-
event.errorCode = apiEvent.errorCode;
|
|
8857
|
-
}
|
|
8858
|
-
if (apiEvent.errorMessage) {
|
|
8859
|
-
event.errorMessage = apiEvent.errorMessage;
|
|
8860
|
-
}
|
|
8861
|
-
if (apiEvent.eventMetadata) {
|
|
8862
|
-
const longRunningToolIdsList = apiEvent.eventMetadata.longRunningToolIds;
|
|
8863
|
-
event.partial = apiEvent.eventMetadata.partial;
|
|
8864
|
-
event.turnComplete = apiEvent.eventMetadata.turnComplete;
|
|
8865
|
-
event.interrupted = apiEvent.eventMetadata.interrupted;
|
|
8866
|
-
event.branch = apiEvent.eventMetadata.branch;
|
|
8867
|
-
event.groundingMetadata = this.decodeGroundingMetadata(
|
|
8868
|
-
apiEvent.eventMetadata.groundingMetadata
|
|
8869
|
-
);
|
|
8870
|
-
event.longRunningToolIds = longRunningToolIdsList ? new Set(longRunningToolIdsList) : void 0;
|
|
8871
|
-
}
|
|
8872
|
-
return event;
|
|
8873
|
-
}
|
|
8874
|
-
decodeContent(content) {
|
|
8875
|
-
if (!content) return void 0;
|
|
8876
|
-
return content;
|
|
8877
9040
|
}
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
9041
|
+
};
|
|
9042
|
+
var InMemoryRunner = class extends Runner {
|
|
9043
|
+
/**
|
|
9044
|
+
* Deprecated. Please don't use. The in-memory session service for the runner.
|
|
9045
|
+
*/
|
|
9046
|
+
_inMemorySessionService;
|
|
9047
|
+
/**
|
|
9048
|
+
* Initializes the InMemoryRunner.
|
|
9049
|
+
*/
|
|
9050
|
+
constructor(agent, { appName = "InMemoryRunner" } = {}) {
|
|
9051
|
+
const inMemorySessionService = new InMemorySessionService();
|
|
9052
|
+
super({
|
|
9053
|
+
appName,
|
|
9054
|
+
agent,
|
|
9055
|
+
artifactService: new InMemoryArtifactService(),
|
|
9056
|
+
sessionService: inMemorySessionService,
|
|
9057
|
+
memoryService: new InMemoryMemoryService()
|
|
9058
|
+
});
|
|
9059
|
+
this._inMemorySessionService = inMemorySessionService;
|
|
8881
9060
|
}
|
|
8882
9061
|
};
|
|
8883
9062
|
|
|
8884
|
-
// src/
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
constructor(config) {
|
|
8890
|
-
super();
|
|
8891
|
-
this.db = config.db;
|
|
8892
|
-
if (!config.skipTableCreation) {
|
|
8893
|
-
this.initializeDatabase().catch((error) => {
|
|
8894
|
-
console.error("Failed to initialize database:", error);
|
|
8895
|
-
});
|
|
8896
|
-
}
|
|
8897
|
-
}
|
|
9063
|
+
// src/agents/agent-builder.ts
|
|
9064
|
+
var AgentBuilder = class _AgentBuilder {
|
|
9065
|
+
config;
|
|
9066
|
+
sessionConfig;
|
|
9067
|
+
agentType = "llm";
|
|
8898
9068
|
/**
|
|
8899
|
-
*
|
|
9069
|
+
* Private constructor - use static create() method
|
|
8900
9070
|
*/
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
return;
|
|
8904
|
-
}
|
|
8905
|
-
try {
|
|
8906
|
-
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(
|
|
8907
|
-
"create_time",
|
|
8908
|
-
"timestamp",
|
|
8909
|
-
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
8910
|
-
).addColumn(
|
|
8911
|
-
"update_time",
|
|
8912
|
-
"timestamp",
|
|
8913
|
-
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
8914
|
-
).addPrimaryKeyConstraint("sessions_pk", ["app_name", "user_id", "id"]).execute();
|
|
8915
|
-
await this.db.schema.createTable("events").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("session_id", "varchar(128)", (col) => col.notNull()).addColumn("invocation_id", "varchar(256)").addColumn("author", "varchar(256)").addColumn("branch", "varchar(256)").addColumn(
|
|
8916
|
-
"timestamp",
|
|
8917
|
-
"timestamp",
|
|
8918
|
-
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)
|
|
8919
|
-
).addColumn("content", "text").addColumn("actions", "text").addColumn("long_running_tool_ids_json", "text").addColumn("grounding_metadata", "text").addColumn("partial", "boolean").addColumn("turn_complete", "boolean").addColumn("error_code", "varchar(256)").addColumn("error_message", "varchar(1024)").addColumn("interrupted", "boolean").addPrimaryKeyConstraint("events_pk", [
|
|
8920
|
-
"id",
|
|
8921
|
-
"app_name",
|
|
8922
|
-
"user_id",
|
|
8923
|
-
"session_id"
|
|
8924
|
-
]).addForeignKeyConstraint(
|
|
8925
|
-
"events_session_fk",
|
|
8926
|
-
["app_name", "user_id", "session_id"],
|
|
8927
|
-
"sessions",
|
|
8928
|
-
["app_name", "user_id", "id"]
|
|
8929
|
-
).execute();
|
|
8930
|
-
await this.db.schema.createTable("app_states").ifNotExists().addColumn("app_name", "varchar(128)", (col) => col.primaryKey()).addColumn("state", "text", (col) => col.defaultTo("{}")).addColumn(
|
|
8931
|
-
"update_time",
|
|
8932
|
-
"timestamp",
|
|
8933
|
-
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
8934
|
-
).execute();
|
|
8935
|
-
await this.db.schema.createTable("user_states").ifNotExists().addColumn("app_name", "varchar(128)", (col) => col.notNull()).addColumn("user_id", "varchar(128)", (col) => col.notNull()).addColumn("state", "text", (col) => col.defaultTo("{}")).addColumn(
|
|
8936
|
-
"update_time",
|
|
8937
|
-
"timestamp",
|
|
8938
|
-
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
8939
|
-
).addPrimaryKeyConstraint("user_states_pk", ["app_name", "user_id"]).execute();
|
|
8940
|
-
await this.db.schema.createIndex("idx_sessions_user_id").ifNotExists().on("sessions").column("user_id").execute();
|
|
8941
|
-
this.initialized = true;
|
|
8942
|
-
} catch (error) {
|
|
8943
|
-
console.error("Error initializing database:", error);
|
|
8944
|
-
throw error;
|
|
8945
|
-
}
|
|
9071
|
+
constructor(name) {
|
|
9072
|
+
this.config = { name };
|
|
8946
9073
|
}
|
|
8947
9074
|
/**
|
|
8948
|
-
*
|
|
9075
|
+
* Create a new AgentBuilder instance
|
|
9076
|
+
* @param name The name of the agent (defaults to "default_agent")
|
|
9077
|
+
* @returns New AgentBuilder instance
|
|
8949
9078
|
*/
|
|
8950
|
-
|
|
8951
|
-
|
|
8952
|
-
await this.initializeDatabase();
|
|
8953
|
-
}
|
|
9079
|
+
static create(name = "default_agent") {
|
|
9080
|
+
return new _AgentBuilder(name);
|
|
8954
9081
|
}
|
|
8955
|
-
|
|
8956
|
-
|
|
9082
|
+
/**
|
|
9083
|
+
* Convenience method to start building with a model directly
|
|
9084
|
+
* @param model The model identifier (e.g., "gemini-2.5-flash")
|
|
9085
|
+
* @returns New AgentBuilder instance with model set
|
|
9086
|
+
*/
|
|
9087
|
+
static withModel(model) {
|
|
9088
|
+
return new _AgentBuilder("default_agent").withModel(model);
|
|
8957
9089
|
}
|
|
8958
9090
|
/**
|
|
8959
|
-
*
|
|
9091
|
+
* Set the model for the agent
|
|
9092
|
+
* @param model The model identifier (e.g., "gemini-2.5-flash")
|
|
9093
|
+
* @returns This builder instance for chaining
|
|
8960
9094
|
*/
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
return JSON.parse(jsonString);
|
|
8965
|
-
} catch {
|
|
8966
|
-
return defaultValue;
|
|
8967
|
-
}
|
|
9095
|
+
withModel(model) {
|
|
9096
|
+
this.config.model = model;
|
|
9097
|
+
return this;
|
|
8968
9098
|
}
|
|
8969
9099
|
/**
|
|
8970
|
-
*
|
|
8971
|
-
*
|
|
9100
|
+
* Set the description for the agent
|
|
9101
|
+
* @param description Agent description
|
|
9102
|
+
* @returns This builder instance for chaining
|
|
8972
9103
|
*/
|
|
8973
|
-
|
|
8974
|
-
|
|
8975
|
-
|
|
8976
|
-
}
|
|
8977
|
-
if (typeof timestamp === "string") {
|
|
8978
|
-
return new Date(timestamp).getTime() / 1e3;
|
|
8979
|
-
}
|
|
8980
|
-
if (typeof timestamp === "number") {
|
|
8981
|
-
return timestamp > 1e10 ? timestamp / 1e3 : timestamp;
|
|
8982
|
-
}
|
|
8983
|
-
return Date.now() / 1e3;
|
|
9104
|
+
withDescription(description) {
|
|
9105
|
+
this.config.description = description;
|
|
9106
|
+
return this;
|
|
8984
9107
|
}
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
8992
|
-
|
|
8993
|
-
if (!appState) {
|
|
8994
|
-
await trx.insertInto("app_states").values({
|
|
8995
|
-
app_name: appName,
|
|
8996
|
-
state: "{}"
|
|
8997
|
-
}).execute();
|
|
8998
|
-
}
|
|
8999
|
-
if (!userState) {
|
|
9000
|
-
await trx.insertInto("user_states").values({
|
|
9001
|
-
app_name: appName,
|
|
9002
|
-
user_id: userId,
|
|
9003
|
-
state: "{}"
|
|
9004
|
-
}).execute();
|
|
9005
|
-
}
|
|
9006
|
-
const { appStateDelta, userStateDelta, sessionStateDelta } = this.extractStateDelta(state);
|
|
9007
|
-
currentAppState = { ...currentAppState, ...appStateDelta };
|
|
9008
|
-
currentUserState = { ...currentUserState, ...userStateDelta };
|
|
9009
|
-
if (Object.keys(appStateDelta).length > 0) {
|
|
9010
|
-
await trx.updateTable("app_states").set({
|
|
9011
|
-
state: JSON.stringify(currentAppState),
|
|
9012
|
-
update_time: sql`CURRENT_TIMESTAMP`
|
|
9013
|
-
}).where("app_name", "=", appName).execute();
|
|
9014
|
-
}
|
|
9015
|
-
if (Object.keys(userStateDelta).length > 0) {
|
|
9016
|
-
await trx.updateTable("user_states").set({
|
|
9017
|
-
state: JSON.stringify(currentUserState),
|
|
9018
|
-
update_time: sql`CURRENT_TIMESTAMP`
|
|
9019
|
-
}).where("app_name", "=", appName).where("user_id", "=", userId).execute();
|
|
9020
|
-
}
|
|
9021
|
-
const result = await trx.insertInto("sessions").values({
|
|
9022
|
-
id,
|
|
9023
|
-
app_name: appName,
|
|
9024
|
-
user_id: userId,
|
|
9025
|
-
state: JSON.stringify(sessionStateDelta)
|
|
9026
|
-
}).returningAll().executeTakeFirstOrThrow();
|
|
9027
|
-
const mergedState = this.mergeState(
|
|
9028
|
-
currentAppState,
|
|
9029
|
-
currentUserState,
|
|
9030
|
-
sessionStateDelta
|
|
9031
|
-
);
|
|
9032
|
-
return {
|
|
9033
|
-
id: result.id,
|
|
9034
|
-
appName: result.app_name,
|
|
9035
|
-
userId: result.user_id,
|
|
9036
|
-
state: mergedState,
|
|
9037
|
-
events: [],
|
|
9038
|
-
// Fixed type annotation
|
|
9039
|
-
lastUpdateTime: this.timestampToUnixSeconds(result.update_time)
|
|
9040
|
-
};
|
|
9041
|
-
});
|
|
9108
|
+
/**
|
|
9109
|
+
* Set the instruction for the agent
|
|
9110
|
+
* @param instruction System instruction for the agent
|
|
9111
|
+
* @returns This builder instance for chaining
|
|
9112
|
+
*/
|
|
9113
|
+
withInstruction(instruction) {
|
|
9114
|
+
this.config.instruction = instruction;
|
|
9115
|
+
return this;
|
|
9042
9116
|
}
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
if (config?.afterTimestamp) {
|
|
9052
|
-
eventQuery = eventQuery.where(
|
|
9053
|
-
"timestamp",
|
|
9054
|
-
">=",
|
|
9055
|
-
new Date(config.afterTimestamp * 1e3)
|
|
9056
|
-
);
|
|
9057
|
-
}
|
|
9058
|
-
if (config?.numRecentEvents) {
|
|
9059
|
-
eventQuery = eventQuery.limit(config.numRecentEvents);
|
|
9060
|
-
}
|
|
9061
|
-
const storageEvents = await eventQuery.execute();
|
|
9062
|
-
const appState = await trx.selectFrom("app_states").selectAll().where("app_name", "=", appName).executeTakeFirst();
|
|
9063
|
-
const userState = await trx.selectFrom("user_states").selectAll().where("app_name", "=", appName).where("user_id", "=", userId).executeTakeFirst();
|
|
9064
|
-
const currentAppState = this.parseJsonSafely(appState?.state, {});
|
|
9065
|
-
const currentUserState = this.parseJsonSafely(userState?.state, {});
|
|
9066
|
-
const sessionState = this.parseJsonSafely(storageSession.state, {});
|
|
9067
|
-
const mergedState = this.mergeState(
|
|
9068
|
-
currentAppState,
|
|
9069
|
-
currentUserState,
|
|
9070
|
-
sessionState
|
|
9071
|
-
);
|
|
9072
|
-
const events = storageEvents.reverse().map((storageEvent) => this.storageEventToEvent(storageEvent));
|
|
9073
|
-
return {
|
|
9074
|
-
id: sessionId,
|
|
9075
|
-
appName,
|
|
9076
|
-
userId,
|
|
9077
|
-
state: mergedState,
|
|
9078
|
-
events,
|
|
9079
|
-
// Now properly typed as Event[]
|
|
9080
|
-
lastUpdateTime: this.timestampToUnixSeconds(storageSession.update_time)
|
|
9081
|
-
};
|
|
9082
|
-
});
|
|
9117
|
+
/**
|
|
9118
|
+
* Add tools to the agent
|
|
9119
|
+
* @param tools Tools to add to the agent
|
|
9120
|
+
* @returns This builder instance for chaining
|
|
9121
|
+
*/
|
|
9122
|
+
withTools(...tools) {
|
|
9123
|
+
this.config.tools = [...this.config.tools || [], ...tools];
|
|
9124
|
+
return this;
|
|
9083
9125
|
}
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9126
|
+
/**
|
|
9127
|
+
* Set the planner for the agent
|
|
9128
|
+
* @param planner The planner to use
|
|
9129
|
+
* @returns This builder instance for chaining
|
|
9130
|
+
*/
|
|
9131
|
+
withPlanner(planner) {
|
|
9132
|
+
this.config.planner = planner;
|
|
9133
|
+
return this;
|
|
9090
9134
|
}
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
// Fixed type annotation
|
|
9101
|
-
lastUpdateTime: this.timestampToUnixSeconds(storageSession.update_time)
|
|
9102
|
-
}));
|
|
9103
|
-
return { sessions };
|
|
9135
|
+
/**
|
|
9136
|
+
* Configure as a sequential agent
|
|
9137
|
+
* @param subAgents Sub-agents to execute in sequence
|
|
9138
|
+
* @returns This builder instance for chaining
|
|
9139
|
+
*/
|
|
9140
|
+
asSequential(subAgents) {
|
|
9141
|
+
this.agentType = "sequential";
|
|
9142
|
+
this.config.subAgents = subAgents;
|
|
9143
|
+
return this;
|
|
9104
9144
|
}
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9145
|
+
/**
|
|
9146
|
+
* Configure as a parallel agent
|
|
9147
|
+
* @param subAgents Sub-agents to execute in parallel
|
|
9148
|
+
* @returns This builder instance for chaining
|
|
9149
|
+
*/
|
|
9150
|
+
asParallel(subAgents) {
|
|
9151
|
+
this.agentType = "parallel";
|
|
9152
|
+
this.config.subAgents = subAgents;
|
|
9153
|
+
return this;
|
|
9108
9154
|
}
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
}
|
|
9121
|
-
const appState = await trx.selectFrom("app_states").selectAll().where("app_name", "=", session.appName).executeTakeFirst();
|
|
9122
|
-
const userState = await trx.selectFrom("user_states").selectAll().where("app_name", "=", session.appName).where("user_id", "=", session.userId).executeTakeFirst();
|
|
9123
|
-
let currentAppState = this.parseJsonSafely(appState?.state, {});
|
|
9124
|
-
let currentUserState = this.parseJsonSafely(userState?.state, {});
|
|
9125
|
-
let sessionState = this.parseJsonSafely(storageSession.state, {});
|
|
9126
|
-
let appStateDelta = {};
|
|
9127
|
-
let userStateDelta = {};
|
|
9128
|
-
let sessionStateDelta = {};
|
|
9129
|
-
if (event.actions?.stateDelta) {
|
|
9130
|
-
const deltas = this.extractStateDelta(event.actions.stateDelta);
|
|
9131
|
-
appStateDelta = deltas.appStateDelta;
|
|
9132
|
-
userStateDelta = deltas.userStateDelta;
|
|
9133
|
-
sessionStateDelta = deltas.sessionStateDelta;
|
|
9134
|
-
}
|
|
9135
|
-
if (Object.keys(appStateDelta).length > 0) {
|
|
9136
|
-
currentAppState = { ...currentAppState, ...appStateDelta };
|
|
9137
|
-
await trx.updateTable("app_states").set({
|
|
9138
|
-
state: JSON.stringify(currentAppState),
|
|
9139
|
-
update_time: sql`CURRENT_TIMESTAMP`
|
|
9140
|
-
}).where("app_name", "=", session.appName).execute();
|
|
9141
|
-
}
|
|
9142
|
-
if (Object.keys(userStateDelta).length > 0) {
|
|
9143
|
-
currentUserState = { ...currentUserState, ...userStateDelta };
|
|
9144
|
-
await trx.updateTable("user_states").set({
|
|
9145
|
-
state: JSON.stringify(currentUserState),
|
|
9146
|
-
update_time: sql`CURRENT_TIMESTAMP`
|
|
9147
|
-
}).where("app_name", "=", session.appName).where("user_id", "=", session.userId).execute();
|
|
9148
|
-
}
|
|
9149
|
-
if (Object.keys(sessionStateDelta).length > 0) {
|
|
9150
|
-
sessionState = { ...sessionState, ...sessionStateDelta };
|
|
9151
|
-
await trx.updateTable("sessions").set({
|
|
9152
|
-
state: JSON.stringify(sessionState),
|
|
9153
|
-
update_time: sql`CURRENT_TIMESTAMP`
|
|
9154
|
-
}).where("app_name", "=", session.appName).where("user_id", "=", session.userId).where("id", "=", session.id).execute();
|
|
9155
|
-
}
|
|
9156
|
-
await trx.insertInto("events").values({
|
|
9157
|
-
...this.eventToStorageEvent(session, event),
|
|
9158
|
-
timestamp: sql`CURRENT_TIMESTAMP`
|
|
9159
|
-
}).execute();
|
|
9160
|
-
const updatedSession = await trx.selectFrom("sessions").select("update_time").where("app_name", "=", session.appName).where("user_id", "=", session.userId).where("id", "=", session.id).executeTakeFirstOrThrow();
|
|
9161
|
-
session.lastUpdateTime = this.timestampToUnixSeconds(
|
|
9162
|
-
updatedSession.update_time
|
|
9163
|
-
);
|
|
9164
|
-
super.appendEvent(session, event);
|
|
9165
|
-
return event;
|
|
9166
|
-
});
|
|
9155
|
+
/**
|
|
9156
|
+
* Configure as a loop agent
|
|
9157
|
+
* @param subAgents Sub-agents to execute iteratively
|
|
9158
|
+
* @param maxIterations Maximum number of iterations
|
|
9159
|
+
* @returns This builder instance for chaining
|
|
9160
|
+
*/
|
|
9161
|
+
asLoop(subAgents, maxIterations = 3) {
|
|
9162
|
+
this.agentType = "loop";
|
|
9163
|
+
this.config.subAgents = subAgents;
|
|
9164
|
+
this.config.maxIterations = maxIterations;
|
|
9165
|
+
return this;
|
|
9167
9166
|
}
|
|
9168
9167
|
/**
|
|
9169
|
-
*
|
|
9168
|
+
* Configure as a LangGraph agent
|
|
9169
|
+
* @param nodes Graph nodes defining the workflow
|
|
9170
|
+
* @param rootNode The starting node name
|
|
9171
|
+
* @returns This builder instance for chaining
|
|
9170
9172
|
*/
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
|
|
9183
|
-
|
|
9173
|
+
asLangGraph(nodes, rootNode) {
|
|
9174
|
+
this.agentType = "langgraph";
|
|
9175
|
+
this.config.nodes = nodes;
|
|
9176
|
+
this.config.rootNode = rootNode;
|
|
9177
|
+
return this;
|
|
9178
|
+
}
|
|
9179
|
+
/**
|
|
9180
|
+
* Configure session management
|
|
9181
|
+
* @param service Session service to use
|
|
9182
|
+
* @param userId User identifier
|
|
9183
|
+
* @param appName Application name
|
|
9184
|
+
* @param memoryService Optional memory service
|
|
9185
|
+
* @param artifactService Optional artifact service
|
|
9186
|
+
* @returns This builder instance for chaining
|
|
9187
|
+
*/
|
|
9188
|
+
withSession(service, userId, appName, memoryService, artifactService) {
|
|
9189
|
+
this.sessionConfig = {
|
|
9190
|
+
service,
|
|
9191
|
+
userId,
|
|
9192
|
+
appName,
|
|
9193
|
+
memoryService,
|
|
9194
|
+
artifactService
|
|
9195
|
+
};
|
|
9196
|
+
return this;
|
|
9197
|
+
}
|
|
9198
|
+
/**
|
|
9199
|
+
* Configure with an in-memory session (for quick setup)
|
|
9200
|
+
* @param appName Application name
|
|
9201
|
+
* @param userId User identifier
|
|
9202
|
+
* @returns This builder instance for chaining
|
|
9203
|
+
*/
|
|
9204
|
+
withQuickSession(appName, userId) {
|
|
9205
|
+
return this.withSession(new InMemorySessionService(), userId, appName);
|
|
9206
|
+
}
|
|
9207
|
+
/**
|
|
9208
|
+
* Build the agent and optionally create runner and session
|
|
9209
|
+
* @returns Built agent with optional runner and session
|
|
9210
|
+
*/
|
|
9211
|
+
async build() {
|
|
9212
|
+
const agent = this.createAgent();
|
|
9213
|
+
let runner;
|
|
9214
|
+
let session;
|
|
9215
|
+
if (this.sessionConfig) {
|
|
9216
|
+
session = await this.sessionConfig.service.createSession(
|
|
9217
|
+
this.sessionConfig.appName,
|
|
9218
|
+
this.sessionConfig.userId
|
|
9219
|
+
);
|
|
9220
|
+
const runnerConfig = {
|
|
9221
|
+
appName: this.sessionConfig.appName,
|
|
9222
|
+
agent,
|
|
9223
|
+
sessionService: this.sessionConfig.service
|
|
9224
|
+
};
|
|
9225
|
+
if (this.sessionConfig.memoryService) {
|
|
9226
|
+
runnerConfig.memoryService = this.sessionConfig.memoryService;
|
|
9184
9227
|
}
|
|
9228
|
+
if (this.sessionConfig.artifactService) {
|
|
9229
|
+
runnerConfig.artifactService = this.sessionConfig.artifactService;
|
|
9230
|
+
}
|
|
9231
|
+
runner = new Runner(runnerConfig);
|
|
9185
9232
|
}
|
|
9186
|
-
return {
|
|
9233
|
+
return { agent, runner, session };
|
|
9187
9234
|
}
|
|
9188
9235
|
/**
|
|
9189
|
-
*
|
|
9236
|
+
* Quick execution helper - build and run a message
|
|
9237
|
+
* @param message Message to send to the agent
|
|
9238
|
+
* @returns Agent response
|
|
9190
9239
|
*/
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9240
|
+
async ask(message) {
|
|
9241
|
+
if (!this.sessionConfig) {
|
|
9242
|
+
const userId = `user-${this.config.name}`;
|
|
9243
|
+
const appName = `session-${this.config.name}`;
|
|
9244
|
+
this.withQuickSession(appName, userId);
|
|
9195
9245
|
}
|
|
9196
|
-
|
|
9197
|
-
|
|
9246
|
+
const { runner, session } = await this.build();
|
|
9247
|
+
if (!runner || !session) {
|
|
9248
|
+
throw new Error("Failed to create runner and session");
|
|
9198
9249
|
}
|
|
9199
|
-
|
|
9250
|
+
let response = "";
|
|
9251
|
+
for await (const event of runner.runAsync({
|
|
9252
|
+
userId: this.sessionConfig.userId,
|
|
9253
|
+
sessionId: session.id,
|
|
9254
|
+
newMessage: {
|
|
9255
|
+
parts: [{ text: message }]
|
|
9256
|
+
}
|
|
9257
|
+
})) {
|
|
9258
|
+
if (event.content?.parts) {
|
|
9259
|
+
const content = event.content.parts.map((part) => part.text || "").join("");
|
|
9260
|
+
if (content) {
|
|
9261
|
+
response += content;
|
|
9262
|
+
}
|
|
9263
|
+
}
|
|
9264
|
+
}
|
|
9265
|
+
return response;
|
|
9200
9266
|
}
|
|
9201
9267
|
/**
|
|
9202
|
-
*
|
|
9268
|
+
* Create the appropriate agent type based on configuration
|
|
9269
|
+
* @returns Created agent instance
|
|
9203
9270
|
*/
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9271
|
+
createAgent() {
|
|
9272
|
+
switch (this.agentType) {
|
|
9273
|
+
case "sequential":
|
|
9274
|
+
if (!this.config.subAgents) {
|
|
9275
|
+
throw new Error("Sub-agents required for sequential agent");
|
|
9276
|
+
}
|
|
9277
|
+
return new SequentialAgent({
|
|
9278
|
+
name: this.config.name,
|
|
9279
|
+
description: this.config.description || "",
|
|
9280
|
+
subAgents: this.config.subAgents
|
|
9281
|
+
});
|
|
9282
|
+
case "parallel":
|
|
9283
|
+
if (!this.config.subAgents) {
|
|
9284
|
+
throw new Error("Sub-agents required for parallel agent");
|
|
9285
|
+
}
|
|
9286
|
+
return new ParallelAgent({
|
|
9287
|
+
name: this.config.name,
|
|
9288
|
+
description: this.config.description || "",
|
|
9289
|
+
subAgents: this.config.subAgents
|
|
9290
|
+
});
|
|
9291
|
+
case "loop":
|
|
9292
|
+
if (!this.config.subAgents) {
|
|
9293
|
+
throw new Error("Sub-agents required for loop agent");
|
|
9294
|
+
}
|
|
9295
|
+
return new LoopAgent({
|
|
9296
|
+
name: this.config.name,
|
|
9297
|
+
description: this.config.description || "",
|
|
9298
|
+
subAgents: this.config.subAgents,
|
|
9299
|
+
maxIterations: this.config.maxIterations || 3
|
|
9300
|
+
});
|
|
9301
|
+
case "langgraph":
|
|
9302
|
+
if (!this.config.nodes || !this.config.rootNode) {
|
|
9303
|
+
throw new Error("Nodes and root node required for LangGraph agent");
|
|
9304
|
+
}
|
|
9305
|
+
return new LangGraphAgent({
|
|
9306
|
+
name: this.config.name,
|
|
9307
|
+
description: this.config.description || "",
|
|
9308
|
+
nodes: this.config.nodes,
|
|
9309
|
+
rootNode: this.config.rootNode
|
|
9310
|
+
});
|
|
9311
|
+
default:
|
|
9312
|
+
return new LlmAgent({
|
|
9313
|
+
name: this.config.name,
|
|
9314
|
+
model: this.config.model,
|
|
9315
|
+
description: this.config.description,
|
|
9316
|
+
instruction: this.config.instruction,
|
|
9317
|
+
tools: this.config.tools,
|
|
9318
|
+
planner: this.config.planner
|
|
9319
|
+
});
|
|
9320
|
+
}
|
|
9223
9321
|
}
|
|
9322
|
+
};
|
|
9323
|
+
|
|
9324
|
+
// src/memory/index.ts
|
|
9325
|
+
var memory_exports = {};
|
|
9326
|
+
__export(memory_exports, {
|
|
9327
|
+
InMemoryMemoryService: () => InMemoryMemoryService
|
|
9328
|
+
});
|
|
9329
|
+
|
|
9330
|
+
// src/sessions/index.ts
|
|
9331
|
+
var sessions_exports = {};
|
|
9332
|
+
__export(sessions_exports, {
|
|
9333
|
+
BaseSessionService: () => BaseSessionService,
|
|
9334
|
+
DatabaseSessionService: () => DatabaseSessionService,
|
|
9335
|
+
InMemorySessionService: () => InMemorySessionService,
|
|
9336
|
+
State: () => State,
|
|
9337
|
+
VertexAiSessionService: () => VertexAiSessionService,
|
|
9338
|
+
createDatabaseSessionService: () => createDatabaseSessionService,
|
|
9339
|
+
createMysqlSessionService: () => createMysqlSessionService,
|
|
9340
|
+
createPostgresSessionService: () => createPostgresSessionService,
|
|
9341
|
+
createSqliteSessionService: () => createSqliteSessionService
|
|
9342
|
+
});
|
|
9343
|
+
|
|
9344
|
+
// src/sessions/vertex-ai-session-service.ts
|
|
9345
|
+
var VertexAiSessionService = class extends BaseSessionService {
|
|
9346
|
+
project;
|
|
9347
|
+
location;
|
|
9348
|
+
agentEngineId;
|
|
9224
9349
|
/**
|
|
9225
|
-
*
|
|
9350
|
+
* Initializes the VertexAiSessionService.
|
|
9226
9351
|
*/
|
|
9227
|
-
|
|
9228
|
-
|
|
9229
|
-
|
|
9230
|
-
|
|
9231
|
-
|
|
9232
|
-
|
|
9233
|
-
|
|
9234
|
-
|
|
9235
|
-
|
|
9236
|
-
|
|
9237
|
-
|
|
9238
|
-
|
|
9239
|
-
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
|
|
9245
|
-
|
|
9352
|
+
constructor(options = {}) {
|
|
9353
|
+
super();
|
|
9354
|
+
this.project = options.project;
|
|
9355
|
+
this.location = options.location;
|
|
9356
|
+
this.agentEngineId = options.agentEngineId;
|
|
9357
|
+
}
|
|
9358
|
+
async createSession(appName, userId, state, sessionId) {
|
|
9359
|
+
if (sessionId) {
|
|
9360
|
+
throw new Error(
|
|
9361
|
+
"User-provided Session id is not supported for VertexAISessionService."
|
|
9362
|
+
);
|
|
9363
|
+
}
|
|
9364
|
+
const reasoningEngineId = this.getReasoningEngineId(appName);
|
|
9365
|
+
const apiClient = this.getApiClient();
|
|
9366
|
+
const sessionJsonDict = { user_id: userId };
|
|
9367
|
+
if (state) {
|
|
9368
|
+
sessionJsonDict.session_state = state;
|
|
9369
|
+
}
|
|
9370
|
+
const apiResponse = await apiClient.async_request({
|
|
9371
|
+
http_method: "POST",
|
|
9372
|
+
path: `reasoningEngines/${reasoningEngineId}/sessions`,
|
|
9373
|
+
request_dict: sessionJsonDict
|
|
9374
|
+
});
|
|
9375
|
+
console.info("Create Session response", apiResponse);
|
|
9376
|
+
const createdSessionId = apiResponse.name.split("/").slice(-3, -2)[0];
|
|
9377
|
+
const operationId = apiResponse.name.split("/").pop();
|
|
9378
|
+
let maxRetryAttempt = 5;
|
|
9379
|
+
let lroResponse = null;
|
|
9380
|
+
while (maxRetryAttempt >= 0) {
|
|
9381
|
+
lroResponse = await apiClient.async_request({
|
|
9382
|
+
http_method: "GET",
|
|
9383
|
+
path: `operations/${operationId}`,
|
|
9384
|
+
request_dict: {}
|
|
9385
|
+
});
|
|
9386
|
+
if (lroResponse?.done) {
|
|
9387
|
+
break;
|
|
9388
|
+
}
|
|
9389
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
9390
|
+
maxRetryAttempt--;
|
|
9391
|
+
}
|
|
9392
|
+
if (!lroResponse || !lroResponse.done) {
|
|
9393
|
+
throw new Error(
|
|
9394
|
+
`Timeout waiting for operation ${operationId} to complete.`
|
|
9395
|
+
);
|
|
9396
|
+
}
|
|
9397
|
+
const getSessionApiResponse = await apiClient.async_request({
|
|
9398
|
+
http_method: "GET",
|
|
9399
|
+
path: `reasoningEngines/${reasoningEngineId}/sessions/${createdSessionId}`,
|
|
9400
|
+
request_dict: {}
|
|
9401
|
+
});
|
|
9402
|
+
const updateTimestamp = new Date(getSessionApiResponse.updateTime).getTime() / 1e3;
|
|
9246
9403
|
return {
|
|
9247
|
-
|
|
9248
|
-
|
|
9249
|
-
|
|
9250
|
-
|
|
9251
|
-
|
|
9252
|
-
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
|
|
9257
|
-
|
|
9258
|
-
|
|
9404
|
+
appName: String(appName),
|
|
9405
|
+
userId: String(userId),
|
|
9406
|
+
id: String(createdSessionId),
|
|
9407
|
+
state: getSessionApiResponse.sessionState || {},
|
|
9408
|
+
events: [],
|
|
9409
|
+
lastUpdateTime: updateTimestamp
|
|
9410
|
+
};
|
|
9411
|
+
}
|
|
9412
|
+
async getSession(appName, userId, sessionId, config) {
|
|
9413
|
+
const reasoningEngineId = this.getReasoningEngineId(appName);
|
|
9414
|
+
const apiClient = this.getApiClient();
|
|
9415
|
+
try {
|
|
9416
|
+
const getSessionApiResponse = await apiClient.async_request({
|
|
9417
|
+
http_method: "GET",
|
|
9418
|
+
path: `reasoningEngines/${reasoningEngineId}/sessions/${sessionId}`,
|
|
9419
|
+
request_dict: {}
|
|
9420
|
+
});
|
|
9421
|
+
const sessionIdFromResponse = getSessionApiResponse.name.split("/").pop();
|
|
9422
|
+
const updateTimestamp = new Date(getSessionApiResponse.updateTime).getTime() / 1e3;
|
|
9423
|
+
const session = {
|
|
9424
|
+
appName: String(appName),
|
|
9425
|
+
userId: String(userId),
|
|
9426
|
+
id: String(sessionIdFromResponse),
|
|
9427
|
+
state: getSessionApiResponse.sessionState || {},
|
|
9428
|
+
events: [],
|
|
9429
|
+
lastUpdateTime: updateTimestamp
|
|
9430
|
+
};
|
|
9431
|
+
let listEventsApiResponse = await apiClient.async_request({
|
|
9432
|
+
http_method: "GET",
|
|
9433
|
+
path: `reasoningEngines/${reasoningEngineId}/sessions/${sessionId}/events`,
|
|
9434
|
+
request_dict: {}
|
|
9435
|
+
});
|
|
9436
|
+
if (listEventsApiResponse.httpHeaders) {
|
|
9437
|
+
return session;
|
|
9438
|
+
}
|
|
9439
|
+
if (listEventsApiResponse.sessionEvents) {
|
|
9440
|
+
session.events.push(
|
|
9441
|
+
...listEventsApiResponse.sessionEvents.map(this.fromApiEvent)
|
|
9442
|
+
);
|
|
9443
|
+
}
|
|
9444
|
+
while (listEventsApiResponse.nextPageToken) {
|
|
9445
|
+
const pageToken = listEventsApiResponse.nextPageToken;
|
|
9446
|
+
listEventsApiResponse = await apiClient.async_request({
|
|
9447
|
+
http_method: "GET",
|
|
9448
|
+
path: `reasoningEngines/${reasoningEngineId}/sessions/${sessionId}/events?pageToken=${encodeURIComponent(pageToken)}`,
|
|
9449
|
+
request_dict: {}
|
|
9450
|
+
});
|
|
9451
|
+
if (listEventsApiResponse.sessionEvents) {
|
|
9452
|
+
session.events.push(
|
|
9453
|
+
...listEventsApiResponse.sessionEvents.map(this.fromApiEvent)
|
|
9454
|
+
);
|
|
9259
9455
|
}
|
|
9260
|
-
|
|
9261
|
-
|
|
9262
|
-
|
|
9263
|
-
|
|
9264
|
-
|
|
9456
|
+
}
|
|
9457
|
+
session.events = session.events.filter(
|
|
9458
|
+
(event) => event.timestamp <= updateTimestamp
|
|
9459
|
+
);
|
|
9460
|
+
session.events.sort((a, b) => a.timestamp - b.timestamp);
|
|
9461
|
+
if (config) {
|
|
9462
|
+
if (config.numRecentEvents) {
|
|
9463
|
+
session.events = session.events.slice(-config.numRecentEvents);
|
|
9464
|
+
} else if (config.afterTimestamp) {
|
|
9465
|
+
let i = session.events.length - 1;
|
|
9466
|
+
while (i >= 0) {
|
|
9467
|
+
if (session.events[i].timestamp < config.afterTimestamp) {
|
|
9468
|
+
break;
|
|
9469
|
+
}
|
|
9470
|
+
i--;
|
|
9471
|
+
}
|
|
9472
|
+
if (i >= 0) {
|
|
9473
|
+
session.events = session.events.slice(i);
|
|
9474
|
+
}
|
|
9265
9475
|
}
|
|
9266
|
-
return false;
|
|
9267
9476
|
}
|
|
9268
|
-
|
|
9477
|
+
return session;
|
|
9478
|
+
} catch (error) {
|
|
9479
|
+
console.error(`Error getting session ${sessionId}:`, error);
|
|
9480
|
+
return void 0;
|
|
9481
|
+
}
|
|
9269
9482
|
}
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
9483
|
+
async listSessions(appName, userId) {
|
|
9484
|
+
const reasoningEngineId = this.getReasoningEngineId(appName);
|
|
9485
|
+
const apiClient = this.getApiClient();
|
|
9486
|
+
let path2 = `reasoningEngines/${reasoningEngineId}/sessions`;
|
|
9487
|
+
if (userId) {
|
|
9488
|
+
const parsedUserId = encodeURIComponent(`"${userId}"`);
|
|
9489
|
+
path2 = `${path2}?filter=user_id=${parsedUserId}`;
|
|
9277
9490
|
}
|
|
9278
|
-
|
|
9279
|
-
|
|
9280
|
-
|
|
9491
|
+
const apiResponse = await apiClient.async_request({
|
|
9492
|
+
http_method: "GET",
|
|
9493
|
+
path: path2,
|
|
9494
|
+
request_dict: {}
|
|
9495
|
+
});
|
|
9496
|
+
if (apiResponse.httpHeaders) {
|
|
9497
|
+
return { sessions: [] };
|
|
9498
|
+
}
|
|
9499
|
+
const sessions = [];
|
|
9500
|
+
if (apiResponse.sessions) {
|
|
9501
|
+
for (const apiSession of apiResponse.sessions) {
|
|
9502
|
+
const session = {
|
|
9503
|
+
appName,
|
|
9504
|
+
userId,
|
|
9505
|
+
id: apiSession.name.split("/").pop(),
|
|
9506
|
+
state: {},
|
|
9507
|
+
events: [],
|
|
9508
|
+
lastUpdateTime: new Date(apiSession.updateTime).getTime() / 1e3
|
|
9509
|
+
};
|
|
9510
|
+
sessions.push(session);
|
|
9281
9511
|
}
|
|
9282
9512
|
}
|
|
9513
|
+
return { sessions };
|
|
9283
9514
|
}
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9287
|
-
|
|
9288
|
-
|
|
9289
|
-
|
|
9290
|
-
|
|
9291
|
-
|
|
9292
|
-
|
|
9293
|
-
|
|
9294
|
-
|
|
9295
|
-
|
|
9296
|
-
|
|
9297
|
-
# or
|
|
9298
|
-
yarn add ${packageName}`
|
|
9299
|
-
);
|
|
9300
|
-
}
|
|
9301
|
-
function createPostgresSessionService(connectionString, options) {
|
|
9302
|
-
let Pool;
|
|
9303
|
-
try {
|
|
9304
|
-
({ Pool } = __require("pg"));
|
|
9305
|
-
} catch (error) {
|
|
9306
|
-
throw createDependencyError("pg", "PostgreSQL");
|
|
9515
|
+
async deleteSession(appName, userId, sessionId) {
|
|
9516
|
+
const reasoningEngineId = this.getReasoningEngineId(appName);
|
|
9517
|
+
const apiClient = this.getApiClient();
|
|
9518
|
+
try {
|
|
9519
|
+
await apiClient.async_request({
|
|
9520
|
+
http_method: "DELETE",
|
|
9521
|
+
path: `reasoningEngines/${reasoningEngineId}/sessions/${sessionId}`,
|
|
9522
|
+
request_dict: {}
|
|
9523
|
+
});
|
|
9524
|
+
} catch (error) {
|
|
9525
|
+
console.error(`Error deleting session ${sessionId}:`, error);
|
|
9526
|
+
throw error;
|
|
9527
|
+
}
|
|
9307
9528
|
}
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
function createMysqlSessionService(connectionString, options) {
|
|
9319
|
-
let createPool;
|
|
9320
|
-
try {
|
|
9321
|
-
({ createPool } = __require("mysql2"));
|
|
9322
|
-
} catch (error) {
|
|
9323
|
-
throw createDependencyError("mysql2", "MySQL");
|
|
9529
|
+
async appendEvent(session, event) {
|
|
9530
|
+
await super.appendEvent(session, event);
|
|
9531
|
+
const reasoningEngineId = this.getReasoningEngineId(session.appName);
|
|
9532
|
+
const apiClient = this.getApiClient();
|
|
9533
|
+
await apiClient.async_request({
|
|
9534
|
+
http_method: "POST",
|
|
9535
|
+
path: `reasoningEngines/${reasoningEngineId}/sessions/${session.id}:appendEvent`,
|
|
9536
|
+
request_dict: this.convertEventToJson(event)
|
|
9537
|
+
});
|
|
9538
|
+
return event;
|
|
9324
9539
|
}
|
|
9325
|
-
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
|
|
9330
|
-
|
|
9331
|
-
}
|
|
9332
|
-
|
|
9333
|
-
|
|
9334
|
-
|
|
9335
|
-
|
|
9336
|
-
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
throw createDependencyError("better-sqlite3", "SQLite");
|
|
9540
|
+
getReasoningEngineId(appName) {
|
|
9541
|
+
if (this.agentEngineId) {
|
|
9542
|
+
return this.agentEngineId;
|
|
9543
|
+
}
|
|
9544
|
+
if (/^\d+$/.test(appName)) {
|
|
9545
|
+
return appName;
|
|
9546
|
+
}
|
|
9547
|
+
const pattern = /^projects\/([a-zA-Z0-9-_]+)\/locations\/([a-zA-Z0-9-_]+)\/reasoningEngines\/(\d+)$/;
|
|
9548
|
+
const match = appName.match(pattern);
|
|
9549
|
+
if (!match) {
|
|
9550
|
+
throw new Error(
|
|
9551
|
+
`App name ${appName} is not valid. It should either be the full ReasoningEngine resource name, or the reasoning engine id.`
|
|
9552
|
+
);
|
|
9553
|
+
}
|
|
9554
|
+
return match[3];
|
|
9341
9555
|
}
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
}
|
|
9349
|
-
|
|
9350
|
-
if (databaseUrl.startsWith("postgres://") || databaseUrl.startsWith("postgresql://")) {
|
|
9351
|
-
return createPostgresSessionService(databaseUrl, options);
|
|
9556
|
+
getApiClient() {
|
|
9557
|
+
const { GoogleGenAI: GoogleGenAI2 } = __require("@google/genai");
|
|
9558
|
+
const client = new GoogleGenAI2({
|
|
9559
|
+
vertexai: true,
|
|
9560
|
+
project: this.project,
|
|
9561
|
+
location: this.location
|
|
9562
|
+
});
|
|
9563
|
+
return client._api_client;
|
|
9352
9564
|
}
|
|
9353
|
-
|
|
9354
|
-
|
|
9565
|
+
convertEventToJson(event) {
|
|
9566
|
+
const metadataJson = {
|
|
9567
|
+
partial: event.partial,
|
|
9568
|
+
turn_complete: event.turnComplete,
|
|
9569
|
+
interrupted: event.interrupted,
|
|
9570
|
+
branch: event.branch,
|
|
9571
|
+
long_running_tool_ids: event.longRunningToolIds ? Array.from(event.longRunningToolIds) : null
|
|
9572
|
+
};
|
|
9573
|
+
if (event.groundingMetadata) {
|
|
9574
|
+
metadataJson.grounding_metadata = event.groundingMetadata;
|
|
9575
|
+
}
|
|
9576
|
+
const eventJson = {
|
|
9577
|
+
author: event.author,
|
|
9578
|
+
invocation_id: event.invocationId,
|
|
9579
|
+
timestamp: {
|
|
9580
|
+
seconds: Math.floor(event.timestamp),
|
|
9581
|
+
nanos: Math.floor(
|
|
9582
|
+
(event.timestamp - Math.floor(event.timestamp)) * 1e9
|
|
9583
|
+
)
|
|
9584
|
+
},
|
|
9585
|
+
error_code: event.errorCode,
|
|
9586
|
+
error_message: event.errorMessage,
|
|
9587
|
+
event_metadata: metadataJson
|
|
9588
|
+
};
|
|
9589
|
+
if (event.actions) {
|
|
9590
|
+
const actionsJson = {
|
|
9591
|
+
skip_summarization: event.actions.skipSummarization,
|
|
9592
|
+
state_delta: event.actions.stateDelta,
|
|
9593
|
+
artifact_delta: event.actions.artifactDelta,
|
|
9594
|
+
transfer_agent: event.actions.transferToAgent,
|
|
9595
|
+
escalate: event.actions.escalate,
|
|
9596
|
+
requested_auth_configs: event.actions.requestedAuthConfigs
|
|
9597
|
+
};
|
|
9598
|
+
eventJson.actions = actionsJson;
|
|
9599
|
+
}
|
|
9600
|
+
if (event.content) {
|
|
9601
|
+
eventJson.content = event.content;
|
|
9602
|
+
}
|
|
9603
|
+
return eventJson;
|
|
9355
9604
|
}
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9605
|
+
fromApiEvent(apiEvent) {
|
|
9606
|
+
let eventActions = new EventActions();
|
|
9607
|
+
if (apiEvent.actions) {
|
|
9608
|
+
eventActions = new EventActions({
|
|
9609
|
+
skipSummarization: apiEvent.actions.skipSummarization,
|
|
9610
|
+
stateDelta: apiEvent.actions.stateDelta || {},
|
|
9611
|
+
artifactDelta: apiEvent.actions.artifactDelta || {},
|
|
9612
|
+
transferToAgent: apiEvent.actions.transferAgent,
|
|
9613
|
+
escalate: apiEvent.actions.escalate,
|
|
9614
|
+
requestedAuthConfigs: apiEvent.actions.requestedAuthConfigs || {}
|
|
9615
|
+
});
|
|
9616
|
+
}
|
|
9617
|
+
const event = new Event({
|
|
9618
|
+
id: apiEvent.name.split("/").pop(),
|
|
9619
|
+
invocationId: apiEvent.invocationId,
|
|
9620
|
+
author: apiEvent.author,
|
|
9621
|
+
actions: eventActions,
|
|
9622
|
+
content: this.decodeContent(apiEvent.content),
|
|
9623
|
+
timestamp: new Date(apiEvent.timestamp).getTime() / 1e3
|
|
9624
|
+
});
|
|
9625
|
+
if (apiEvent.errorCode) {
|
|
9626
|
+
event.errorCode = apiEvent.errorCode;
|
|
9627
|
+
}
|
|
9628
|
+
if (apiEvent.errorMessage) {
|
|
9629
|
+
event.errorMessage = apiEvent.errorMessage;
|
|
9630
|
+
}
|
|
9631
|
+
if (apiEvent.eventMetadata) {
|
|
9632
|
+
const longRunningToolIdsList = apiEvent.eventMetadata.longRunningToolIds;
|
|
9633
|
+
event.partial = apiEvent.eventMetadata.partial;
|
|
9634
|
+
event.turnComplete = apiEvent.eventMetadata.turnComplete;
|
|
9635
|
+
event.interrupted = apiEvent.eventMetadata.interrupted;
|
|
9636
|
+
event.branch = apiEvent.eventMetadata.branch;
|
|
9637
|
+
event.groundingMetadata = this.decodeGroundingMetadata(
|
|
9638
|
+
apiEvent.eventMetadata.groundingMetadata
|
|
9639
|
+
);
|
|
9640
|
+
event.longRunningToolIds = longRunningToolIdsList ? new Set(longRunningToolIdsList) : void 0;
|
|
9641
|
+
}
|
|
9642
|
+
return event;
|
|
9643
|
+
}
|
|
9644
|
+
decodeContent(content) {
|
|
9645
|
+
if (!content) return void 0;
|
|
9646
|
+
return content;
|
|
9647
|
+
}
|
|
9648
|
+
decodeGroundingMetadata(groundingMetadata) {
|
|
9649
|
+
if (!groundingMetadata) return void 0;
|
|
9650
|
+
return groundingMetadata;
|
|
9651
|
+
}
|
|
9652
|
+
};
|
|
9653
|
+
|
|
9654
|
+
// src/sessions/database-session-service.ts
|
|
9655
|
+
import { sql } from "kysely";
|
|
9656
|
+
var DatabaseSessionService = class extends BaseSessionService {
|
|
9657
|
+
db;
|
|
9658
|
+
initialized = false;
|
|
9659
|
+
constructor(config) {
|
|
9660
|
+
super();
|
|
9661
|
+
this.db = config.db;
|
|
9662
|
+
if (!config.skipTableCreation) {
|
|
9663
|
+
this.initializeDatabase().catch((error) => {
|
|
9664
|
+
console.error("Failed to initialize database:", error);
|
|
9665
|
+
});
|
|
9666
|
+
}
|
|
9667
|
+
}
|
|
9668
|
+
/**
|
|
9669
|
+
* Initialize the database by creating required tables if they don't exist
|
|
9670
|
+
*/
|
|
9671
|
+
async initializeDatabase() {
|
|
9672
|
+
if (this.initialized) {
|
|
9673
|
+
return;
|
|
9674
|
+
}
|
|
9675
|
+
try {
|
|
9676
|
+
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(
|
|
9677
|
+
"create_time",
|
|
9678
|
+
"timestamp",
|
|
9679
|
+
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
9680
|
+
).addColumn(
|
|
9681
|
+
"update_time",
|
|
9682
|
+
"timestamp",
|
|
9683
|
+
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
9684
|
+
).addPrimaryKeyConstraint("sessions_pk", ["app_name", "user_id", "id"]).execute();
|
|
9685
|
+
await this.db.schema.createTable("events").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("session_id", "varchar(128)", (col) => col.notNull()).addColumn("invocation_id", "varchar(256)").addColumn("author", "varchar(256)").addColumn("branch", "varchar(256)").addColumn(
|
|
9686
|
+
"timestamp",
|
|
9687
|
+
"timestamp",
|
|
9688
|
+
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`)
|
|
9689
|
+
).addColumn("content", "text").addColumn("actions", "text").addColumn("long_running_tool_ids_json", "text").addColumn("grounding_metadata", "text").addColumn("partial", "boolean").addColumn("turn_complete", "boolean").addColumn("error_code", "varchar(256)").addColumn("error_message", "varchar(1024)").addColumn("interrupted", "boolean").addPrimaryKeyConstraint("events_pk", [
|
|
9690
|
+
"id",
|
|
9691
|
+
"app_name",
|
|
9692
|
+
"user_id",
|
|
9693
|
+
"session_id"
|
|
9694
|
+
]).addForeignKeyConstraint(
|
|
9695
|
+
"events_session_fk",
|
|
9696
|
+
["app_name", "user_id", "session_id"],
|
|
9697
|
+
"sessions",
|
|
9698
|
+
["app_name", "user_id", "id"]
|
|
9699
|
+
).execute();
|
|
9700
|
+
await this.db.schema.createTable("app_states").ifNotExists().addColumn("app_name", "varchar(128)", (col) => col.primaryKey()).addColumn("state", "text", (col) => col.defaultTo("{}")).addColumn(
|
|
9701
|
+
"update_time",
|
|
9702
|
+
"timestamp",
|
|
9703
|
+
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
9704
|
+
).execute();
|
|
9705
|
+
await this.db.schema.createTable("user_states").ifNotExists().addColumn("app_name", "varchar(128)", (col) => col.notNull()).addColumn("user_id", "varchar(128)", (col) => col.notNull()).addColumn("state", "text", (col) => col.defaultTo("{}")).addColumn(
|
|
9706
|
+
"update_time",
|
|
9707
|
+
"timestamp",
|
|
9708
|
+
(col) => col.defaultTo(sql`CURRENT_TIMESTAMP`).notNull()
|
|
9709
|
+
).addPrimaryKeyConstraint("user_states_pk", ["app_name", "user_id"]).execute();
|
|
9710
|
+
await this.db.schema.createIndex("idx_sessions_user_id").ifNotExists().on("sessions").column("user_id").execute();
|
|
9711
|
+
this.initialized = true;
|
|
9712
|
+
} catch (error) {
|
|
9713
|
+
console.error("Error initializing database:", error);
|
|
9714
|
+
throw error;
|
|
9715
|
+
}
|
|
9359
9716
|
}
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
} from "@google-cloud/storage";
|
|
9368
|
-
var logger9 = new Logger({ name: "GcsArtifactService" });
|
|
9369
|
-
var GcsArtifactService = class {
|
|
9370
|
-
bucketName;
|
|
9371
|
-
storageClient;
|
|
9372
|
-
bucket;
|
|
9373
|
-
constructor(bucketName, options) {
|
|
9374
|
-
this.bucketName = bucketName;
|
|
9375
|
-
this.storageClient = new Storage(options);
|
|
9376
|
-
this.bucket = this.storageClient.bucket(this.bucketName);
|
|
9717
|
+
/**
|
|
9718
|
+
* Ensure database is initialized before any operation
|
|
9719
|
+
*/
|
|
9720
|
+
async ensureInitialized() {
|
|
9721
|
+
if (!this.initialized) {
|
|
9722
|
+
await this.initializeDatabase();
|
|
9723
|
+
}
|
|
9377
9724
|
}
|
|
9378
|
-
|
|
9379
|
-
return
|
|
9725
|
+
generateSessionId() {
|
|
9726
|
+
return `session-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
9380
9727
|
}
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9728
|
+
/**
|
|
9729
|
+
* Helper to safely parse JSON strings
|
|
9730
|
+
*/
|
|
9731
|
+
parseJsonSafely(jsonString, defaultValue) {
|
|
9732
|
+
if (!jsonString) return defaultValue;
|
|
9733
|
+
try {
|
|
9734
|
+
return JSON.parse(jsonString);
|
|
9735
|
+
} catch {
|
|
9736
|
+
return defaultValue;
|
|
9384
9737
|
}
|
|
9385
|
-
return `${appName}/${userId}/${sessionId}/${filename}/${version}`;
|
|
9386
9738
|
}
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
}
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
|
|
9402
|
-
);
|
|
9403
|
-
const blob = this.bucket.file(blobName);
|
|
9404
|
-
await blob.save(artifact.inlineData.data, {
|
|
9405
|
-
contentType: artifact.inlineData.mimeType,
|
|
9406
|
-
preconditionOpts: { ifGenerationMatch: 0 }
|
|
9407
|
-
});
|
|
9408
|
-
return version;
|
|
9739
|
+
/**
|
|
9740
|
+
* Convert database timestamp to Unix seconds
|
|
9741
|
+
* Handles different timestamp formats from different databases
|
|
9742
|
+
*/
|
|
9743
|
+
timestampToUnixSeconds(timestamp) {
|
|
9744
|
+
if (timestamp instanceof Date) {
|
|
9745
|
+
return timestamp.getTime() / 1e3;
|
|
9746
|
+
}
|
|
9747
|
+
if (typeof timestamp === "string") {
|
|
9748
|
+
return new Date(timestamp).getTime() / 1e3;
|
|
9749
|
+
}
|
|
9750
|
+
if (typeof timestamp === "number") {
|
|
9751
|
+
return timestamp > 1e10 ? timestamp / 1e3 : timestamp;
|
|
9752
|
+
}
|
|
9753
|
+
return Date.now() / 1e3;
|
|
9409
9754
|
}
|
|
9410
|
-
async
|
|
9411
|
-
|
|
9412
|
-
const
|
|
9413
|
-
|
|
9414
|
-
const
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9755
|
+
async createSession(appName, userId, state, sessionId) {
|
|
9756
|
+
await this.ensureInitialized();
|
|
9757
|
+
const id = sessionId?.trim() || this.generateSessionId();
|
|
9758
|
+
return await this.db.transaction().execute(async (trx) => {
|
|
9759
|
+
const appState = await trx.selectFrom("app_states").selectAll().where("app_name", "=", appName).executeTakeFirst();
|
|
9760
|
+
const userState = await trx.selectFrom("user_states").selectAll().where("app_name", "=", appName).where("user_id", "=", userId).executeTakeFirst();
|
|
9761
|
+
let currentAppState = this.parseJsonSafely(appState?.state, {});
|
|
9762
|
+
let currentUserState = this.parseJsonSafely(userState?.state, {});
|
|
9763
|
+
if (!appState) {
|
|
9764
|
+
await trx.insertInto("app_states").values({
|
|
9765
|
+
app_name: appName,
|
|
9766
|
+
state: "{}"
|
|
9767
|
+
}).execute();
|
|
9422
9768
|
}
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
filename,
|
|
9430
|
-
version
|
|
9431
|
-
);
|
|
9432
|
-
const blob = this.bucket.file(blobName);
|
|
9433
|
-
try {
|
|
9434
|
-
const [metadata] = await blob.getMetadata();
|
|
9435
|
-
const [artifactBuffer] = await blob.download();
|
|
9436
|
-
if (!artifactBuffer) {
|
|
9437
|
-
return null;
|
|
9769
|
+
if (!userState) {
|
|
9770
|
+
await trx.insertInto("user_states").values({
|
|
9771
|
+
app_name: appName,
|
|
9772
|
+
user_id: userId,
|
|
9773
|
+
state: "{}"
|
|
9774
|
+
}).execute();
|
|
9438
9775
|
}
|
|
9439
|
-
const
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
if (error?.code === 404) {
|
|
9448
|
-
return null;
|
|
9776
|
+
const { appStateDelta, userStateDelta, sessionStateDelta } = this.extractStateDelta(state);
|
|
9777
|
+
currentAppState = { ...currentAppState, ...appStateDelta };
|
|
9778
|
+
currentUserState = { ...currentUserState, ...userStateDelta };
|
|
9779
|
+
if (Object.keys(appStateDelta).length > 0) {
|
|
9780
|
+
await trx.updateTable("app_states").set({
|
|
9781
|
+
state: JSON.stringify(currentAppState),
|
|
9782
|
+
update_time: sql`CURRENT_TIMESTAMP`
|
|
9783
|
+
}).where("app_name", "=", appName).execute();
|
|
9449
9784
|
}
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
const filenames = /* @__PURE__ */ new Set();
|
|
9456
|
-
const processBlobs = (blobNames) => {
|
|
9457
|
-
for (const name of blobNames) {
|
|
9458
|
-
const parts = name.split("/");
|
|
9459
|
-
if (parts.length === 5) {
|
|
9460
|
-
const filename = parts[3];
|
|
9461
|
-
filenames.add(filename);
|
|
9462
|
-
}
|
|
9785
|
+
if (Object.keys(userStateDelta).length > 0) {
|
|
9786
|
+
await trx.updateTable("user_states").set({
|
|
9787
|
+
state: JSON.stringify(currentUserState),
|
|
9788
|
+
update_time: sql`CURRENT_TIMESTAMP`
|
|
9789
|
+
}).where("app_name", "=", appName).where("user_id", "=", userId).execute();
|
|
9463
9790
|
}
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
const { appName, userId, sessionId, filename } = args;
|
|
9475
|
-
const versions = await this.listVersions({
|
|
9476
|
-
appName,
|
|
9477
|
-
userId,
|
|
9478
|
-
sessionId,
|
|
9479
|
-
filename
|
|
9480
|
-
});
|
|
9481
|
-
const deletePromises = versions.map((version) => {
|
|
9482
|
-
const blobName = this.getBlobName(
|
|
9483
|
-
appName,
|
|
9484
|
-
userId,
|
|
9485
|
-
sessionId,
|
|
9486
|
-
filename,
|
|
9487
|
-
version
|
|
9791
|
+
const result = await trx.insertInto("sessions").values({
|
|
9792
|
+
id,
|
|
9793
|
+
app_name: appName,
|
|
9794
|
+
user_id: userId,
|
|
9795
|
+
state: JSON.stringify(sessionStateDelta)
|
|
9796
|
+
}).returningAll().executeTakeFirstOrThrow();
|
|
9797
|
+
const mergedState = this.mergeState(
|
|
9798
|
+
currentAppState,
|
|
9799
|
+
currentUserState,
|
|
9800
|
+
sessionStateDelta
|
|
9488
9801
|
);
|
|
9489
|
-
return
|
|
9802
|
+
return {
|
|
9803
|
+
id: result.id,
|
|
9804
|
+
appName: result.app_name,
|
|
9805
|
+
userId: result.user_id,
|
|
9806
|
+
state: mergedState,
|
|
9807
|
+
events: [],
|
|
9808
|
+
// Fixed type annotation
|
|
9809
|
+
lastUpdateTime: this.timestampToUnixSeconds(result.update_time)
|
|
9810
|
+
};
|
|
9490
9811
|
});
|
|
9491
|
-
await Promise.all(deletePromises);
|
|
9492
9812
|
}
|
|
9493
|
-
async
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9499
|
-
const parts = blob.name.split("/");
|
|
9500
|
-
if (parts.length === 5) {
|
|
9501
|
-
const versionStr = parts[4];
|
|
9502
|
-
const versionNum = Number.parseInt(versionStr, 10);
|
|
9503
|
-
if (!Number.isNaN(versionNum)) {
|
|
9504
|
-
versions.push(versionNum);
|
|
9505
|
-
}
|
|
9813
|
+
async getSession(appName, userId, sessionId, config) {
|
|
9814
|
+
await this.ensureInitialized();
|
|
9815
|
+
return await this.db.transaction().execute(async (trx) => {
|
|
9816
|
+
const storageSession = await trx.selectFrom("sessions").selectAll().where("app_name", "=", appName).where("user_id", "=", userId).where("id", "=", sessionId).executeTakeFirst();
|
|
9817
|
+
if (!storageSession) {
|
|
9818
|
+
return void 0;
|
|
9506
9819
|
}
|
|
9507
|
-
|
|
9508
|
-
|
|
9820
|
+
let eventQuery = trx.selectFrom("events").selectAll().where("session_id", "=", sessionId).orderBy("timestamp", "desc");
|
|
9821
|
+
if (config?.afterTimestamp) {
|
|
9822
|
+
eventQuery = eventQuery.where(
|
|
9823
|
+
"timestamp",
|
|
9824
|
+
">=",
|
|
9825
|
+
new Date(config.afterTimestamp * 1e3)
|
|
9826
|
+
);
|
|
9827
|
+
}
|
|
9828
|
+
if (config?.numRecentEvents) {
|
|
9829
|
+
eventQuery = eventQuery.limit(config.numRecentEvents);
|
|
9830
|
+
}
|
|
9831
|
+
const storageEvents = await eventQuery.execute();
|
|
9832
|
+
const appState = await trx.selectFrom("app_states").selectAll().where("app_name", "=", appName).executeTakeFirst();
|
|
9833
|
+
const userState = await trx.selectFrom("user_states").selectAll().where("app_name", "=", appName).where("user_id", "=", userId).executeTakeFirst();
|
|
9834
|
+
const currentAppState = this.parseJsonSafely(appState?.state, {});
|
|
9835
|
+
const currentUserState = this.parseJsonSafely(userState?.state, {});
|
|
9836
|
+
const sessionState = this.parseJsonSafely(storageSession.state, {});
|
|
9837
|
+
const mergedState = this.mergeState(
|
|
9838
|
+
currentAppState,
|
|
9839
|
+
currentUserState,
|
|
9840
|
+
sessionState
|
|
9841
|
+
);
|
|
9842
|
+
const events = storageEvents.reverse().map((storageEvent) => this.storageEventToEvent(storageEvent));
|
|
9843
|
+
return {
|
|
9844
|
+
id: sessionId,
|
|
9845
|
+
appName,
|
|
9846
|
+
userId,
|
|
9847
|
+
state: mergedState,
|
|
9848
|
+
events,
|
|
9849
|
+
// Now properly typed as Event[]
|
|
9850
|
+
lastUpdateTime: this.timestampToUnixSeconds(storageSession.update_time)
|
|
9851
|
+
};
|
|
9852
|
+
});
|
|
9509
9853
|
}
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
artifacts = /* @__PURE__ */ new Map();
|
|
9517
|
-
fileHasUserNamespace(filename) {
|
|
9518
|
-
return filename.startsWith("user:");
|
|
9854
|
+
async updateSession(session) {
|
|
9855
|
+
await this.ensureInitialized();
|
|
9856
|
+
await this.db.updateTable("sessions").set({
|
|
9857
|
+
state: JSON.stringify(session.state),
|
|
9858
|
+
update_time: sql`CURRENT_TIMESTAMP`
|
|
9859
|
+
}).where("app_name", "=", session.appName).where("user_id", "=", session.userId).where("id", "=", session.id).execute();
|
|
9519
9860
|
}
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9861
|
+
async listSessions(appName, userId) {
|
|
9862
|
+
await this.ensureInitialized();
|
|
9863
|
+
const results = await this.db.selectFrom("sessions").selectAll().where("app_name", "=", appName).where("user_id", "=", userId).execute();
|
|
9864
|
+
const sessions = results.map((storageSession) => ({
|
|
9865
|
+
id: storageSession.id,
|
|
9866
|
+
appName: storageSession.app_name,
|
|
9867
|
+
userId: storageSession.user_id,
|
|
9868
|
+
state: {},
|
|
9869
|
+
events: [],
|
|
9870
|
+
// Fixed type annotation
|
|
9871
|
+
lastUpdateTime: this.timestampToUnixSeconds(storageSession.update_time)
|
|
9872
|
+
}));
|
|
9873
|
+
return { sessions };
|
|
9525
9874
|
}
|
|
9526
|
-
async
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
if (!this.artifacts.has(path2)) {
|
|
9530
|
-
this.artifacts.set(path2, []);
|
|
9531
|
-
}
|
|
9532
|
-
const versions = this.artifacts.get(path2);
|
|
9533
|
-
const version = versions.length;
|
|
9534
|
-
versions.push(artifact);
|
|
9535
|
-
return version;
|
|
9875
|
+
async deleteSession(appName, userId, sessionId) {
|
|
9876
|
+
await this.ensureInitialized();
|
|
9877
|
+
await this.db.deleteFrom("sessions").where("app_name", "=", appName).where("user_id", "=", userId).where("id", "=", sessionId).execute();
|
|
9536
9878
|
}
|
|
9537
|
-
async
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
if (!versions || versions.length === 0) {
|
|
9542
|
-
return null;
|
|
9543
|
-
}
|
|
9544
|
-
let targetVersion = version;
|
|
9545
|
-
if (targetVersion === void 0 || targetVersion === null) {
|
|
9546
|
-
targetVersion = versions.length - 1;
|
|
9547
|
-
}
|
|
9548
|
-
if (targetVersion < 0) {
|
|
9549
|
-
targetVersion = versions.length + targetVersion;
|
|
9550
|
-
}
|
|
9551
|
-
if (targetVersion < 0 || targetVersion >= versions.length) {
|
|
9552
|
-
return null;
|
|
9879
|
+
async appendEvent(session, event) {
|
|
9880
|
+
await this.ensureInitialized();
|
|
9881
|
+
if (event.partial) {
|
|
9882
|
+
return event;
|
|
9553
9883
|
}
|
|
9554
|
-
return
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
const filenames = [];
|
|
9561
|
-
for (const path2 of this.artifacts.keys()) {
|
|
9562
|
-
if (path2.startsWith(sessionPrefix)) {
|
|
9563
|
-
const filename = path2.substring(sessionPrefix.length);
|
|
9564
|
-
filenames.push(filename);
|
|
9565
|
-
} else if (path2.startsWith(userNamespacePrefix)) {
|
|
9566
|
-
const filename = path2.substring(userNamespacePrefix.length);
|
|
9567
|
-
filenames.push(filename);
|
|
9884
|
+
return await this.db.transaction().execute(async (trx) => {
|
|
9885
|
+
const storageSession = await trx.selectFrom("sessions").selectAll().where("app_name", "=", session.appName).where("user_id", "=", session.userId).where("id", "=", session.id).executeTakeFirstOrThrow();
|
|
9886
|
+
if (this.timestampToUnixSeconds(storageSession.update_time) > session.lastUpdateTime) {
|
|
9887
|
+
throw new Error(
|
|
9888
|
+
`The last_update_time provided in the session object ${new Date(session.lastUpdateTime * 1e3).toISOString()} is earlier than the update_time in the storage_session ${storageSession.update_time.toISOString()}. Please check if it is a stale session.`
|
|
9889
|
+
);
|
|
9568
9890
|
}
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9576
|
-
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9580
|
-
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
}
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
|
|
9604
|
-
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
|
|
9615
|
-
nlPlanningResponseProcessor: () => responseProcessor,
|
|
9616
|
-
populateClientFunctionCallId: () => populateClientFunctionCallId,
|
|
9617
|
-
removeClientFunctionCallId: () => removeClientFunctionCallId
|
|
9618
|
-
});
|
|
9619
|
-
|
|
9620
|
-
// src/runners.ts
|
|
9621
|
-
import { SpanStatusCode } from "@opentelemetry/api";
|
|
9622
|
-
init_logger();
|
|
9623
|
-
var logger11 = new Logger({ name: "Runner" });
|
|
9624
|
-
function _findFunctionCallEventIfLastEventIsFunctionResponse(session) {
|
|
9625
|
-
const events = session.events;
|
|
9626
|
-
if (!events || events.length === 0) {
|
|
9627
|
-
return null;
|
|
9891
|
+
const appState = await trx.selectFrom("app_states").selectAll().where("app_name", "=", session.appName).executeTakeFirst();
|
|
9892
|
+
const userState = await trx.selectFrom("user_states").selectAll().where("app_name", "=", session.appName).where("user_id", "=", session.userId).executeTakeFirst();
|
|
9893
|
+
let currentAppState = this.parseJsonSafely(appState?.state, {});
|
|
9894
|
+
let currentUserState = this.parseJsonSafely(userState?.state, {});
|
|
9895
|
+
let sessionState = this.parseJsonSafely(storageSession.state, {});
|
|
9896
|
+
let appStateDelta = {};
|
|
9897
|
+
let userStateDelta = {};
|
|
9898
|
+
let sessionStateDelta = {};
|
|
9899
|
+
if (event.actions?.stateDelta) {
|
|
9900
|
+
const deltas = this.extractStateDelta(event.actions.stateDelta);
|
|
9901
|
+
appStateDelta = deltas.appStateDelta;
|
|
9902
|
+
userStateDelta = deltas.userStateDelta;
|
|
9903
|
+
sessionStateDelta = deltas.sessionStateDelta;
|
|
9904
|
+
}
|
|
9905
|
+
if (Object.keys(appStateDelta).length > 0) {
|
|
9906
|
+
currentAppState = { ...currentAppState, ...appStateDelta };
|
|
9907
|
+
await trx.updateTable("app_states").set({
|
|
9908
|
+
state: JSON.stringify(currentAppState),
|
|
9909
|
+
update_time: sql`CURRENT_TIMESTAMP`
|
|
9910
|
+
}).where("app_name", "=", session.appName).execute();
|
|
9911
|
+
}
|
|
9912
|
+
if (Object.keys(userStateDelta).length > 0) {
|
|
9913
|
+
currentUserState = { ...currentUserState, ...userStateDelta };
|
|
9914
|
+
await trx.updateTable("user_states").set({
|
|
9915
|
+
state: JSON.stringify(currentUserState),
|
|
9916
|
+
update_time: sql`CURRENT_TIMESTAMP`
|
|
9917
|
+
}).where("app_name", "=", session.appName).where("user_id", "=", session.userId).execute();
|
|
9918
|
+
}
|
|
9919
|
+
if (Object.keys(sessionStateDelta).length > 0) {
|
|
9920
|
+
sessionState = { ...sessionState, ...sessionStateDelta };
|
|
9921
|
+
await trx.updateTable("sessions").set({
|
|
9922
|
+
state: JSON.stringify(sessionState),
|
|
9923
|
+
update_time: sql`CURRENT_TIMESTAMP`
|
|
9924
|
+
}).where("app_name", "=", session.appName).where("user_id", "=", session.userId).where("id", "=", session.id).execute();
|
|
9925
|
+
}
|
|
9926
|
+
await trx.insertInto("events").values({
|
|
9927
|
+
...this.eventToStorageEvent(session, event),
|
|
9928
|
+
timestamp: sql`CURRENT_TIMESTAMP`
|
|
9929
|
+
}).execute();
|
|
9930
|
+
const updatedSession = await trx.selectFrom("sessions").select("update_time").where("app_name", "=", session.appName).where("user_id", "=", session.userId).where("id", "=", session.id).executeTakeFirstOrThrow();
|
|
9931
|
+
session.lastUpdateTime = this.timestampToUnixSeconds(
|
|
9932
|
+
updatedSession.update_time
|
|
9933
|
+
);
|
|
9934
|
+
super.appendEvent(session, event);
|
|
9935
|
+
return event;
|
|
9936
|
+
});
|
|
9628
9937
|
}
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
const
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
|
|
9938
|
+
/**
|
|
9939
|
+
* Extract state deltas based on prefixes (similar to Python implementation)
|
|
9940
|
+
*/
|
|
9941
|
+
extractStateDelta(state) {
|
|
9942
|
+
const appStateDelta = {};
|
|
9943
|
+
const userStateDelta = {};
|
|
9944
|
+
const sessionStateDelta = {};
|
|
9945
|
+
if (state) {
|
|
9946
|
+
for (const [key, value] of Object.entries(state)) {
|
|
9947
|
+
if (key.startsWith("app_")) {
|
|
9948
|
+
appStateDelta[key.substring(4)] = value;
|
|
9949
|
+
} else if (key.startsWith("user_")) {
|
|
9950
|
+
userStateDelta[key.substring(5)] = value;
|
|
9951
|
+
} else if (!key.startsWith("temp_")) {
|
|
9952
|
+
sessionStateDelta[key] = value;
|
|
9641
9953
|
}
|
|
9642
9954
|
}
|
|
9643
9955
|
}
|
|
9956
|
+
return { appStateDelta, userStateDelta, sessionStateDelta };
|
|
9644
9957
|
}
|
|
9645
|
-
return null;
|
|
9646
|
-
}
|
|
9647
|
-
var Runner = class {
|
|
9648
|
-
/**
|
|
9649
|
-
* The app name of the runner.
|
|
9650
|
-
*/
|
|
9651
|
-
appName;
|
|
9652
|
-
/**
|
|
9653
|
-
* The root agent to run.
|
|
9654
|
-
*/
|
|
9655
|
-
agent;
|
|
9656
|
-
/**
|
|
9657
|
-
* The artifact service for the runner.
|
|
9658
|
-
*/
|
|
9659
|
-
artifactService;
|
|
9660
|
-
/**
|
|
9661
|
-
* The session service for the runner.
|
|
9662
|
-
*/
|
|
9663
|
-
sessionService;
|
|
9664
9958
|
/**
|
|
9665
|
-
*
|
|
9959
|
+
* Merge states for response (similar to Python implementation)
|
|
9666
9960
|
*/
|
|
9667
|
-
|
|
9961
|
+
mergeState(appState, userState, sessionState) {
|
|
9962
|
+
const mergedState = { ...sessionState };
|
|
9963
|
+
for (const [key, value] of Object.entries(appState)) {
|
|
9964
|
+
mergedState[`app_${key}`] = value;
|
|
9965
|
+
}
|
|
9966
|
+
for (const [key, value] of Object.entries(userState)) {
|
|
9967
|
+
mergedState[`user_${key}`] = value;
|
|
9968
|
+
}
|
|
9969
|
+
return mergedState;
|
|
9970
|
+
}
|
|
9668
9971
|
/**
|
|
9669
|
-
*
|
|
9972
|
+
* Convert Event to storage event format
|
|
9670
9973
|
*/
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9974
|
+
eventToStorageEvent(session, event) {
|
|
9975
|
+
return {
|
|
9976
|
+
id: event.id,
|
|
9977
|
+
app_name: session.appName,
|
|
9978
|
+
user_id: session.userId,
|
|
9979
|
+
session_id: session.id,
|
|
9980
|
+
invocation_id: event.invocationId || "",
|
|
9981
|
+
author: event.author || "",
|
|
9982
|
+
branch: event.branch || null,
|
|
9983
|
+
content: event.content ? JSON.stringify(event.content) : null,
|
|
9984
|
+
actions: event.actions ? JSON.stringify(event.actions) : null,
|
|
9985
|
+
long_running_tool_ids_json: event.longRunningToolIds ? JSON.stringify(Array.from(event.longRunningToolIds)) : null,
|
|
9986
|
+
grounding_metadata: event.groundingMetadata ? JSON.stringify(event.groundingMetadata) : null,
|
|
9987
|
+
partial: event.partial || null,
|
|
9988
|
+
turn_complete: event.turnComplete || null,
|
|
9989
|
+
error_code: event.errorCode || null,
|
|
9990
|
+
error_message: event.errorMessage || null,
|
|
9991
|
+
interrupted: event.interrupted || null
|
|
9992
|
+
};
|
|
9683
9993
|
}
|
|
9684
9994
|
/**
|
|
9685
|
-
*
|
|
9686
|
-
* NOTE: This sync interface is only for local testing and convenience purpose.
|
|
9687
|
-
* Consider using `runAsync` for production usage.
|
|
9995
|
+
* Convert storage event to Event format - Fixed to match Event interface
|
|
9688
9996
|
*/
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9696
|
-
|
|
9697
|
-
|
|
9698
|
-
|
|
9699
|
-
|
|
9700
|
-
|
|
9701
|
-
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
}
|
|
9708
|
-
} finally {
|
|
9709
|
-
eventQueue.push(null);
|
|
9710
|
-
asyncCompleted = true;
|
|
9711
|
-
}
|
|
9997
|
+
storageEventToEvent(storageEvent) {
|
|
9998
|
+
const baseEvent = {
|
|
9999
|
+
id: storageEvent.id,
|
|
10000
|
+
invocationId: storageEvent.invocation_id,
|
|
10001
|
+
author: storageEvent.author,
|
|
10002
|
+
branch: storageEvent.branch || void 0,
|
|
10003
|
+
timestamp: this.timestampToUnixSeconds(storageEvent.timestamp),
|
|
10004
|
+
content: storageEvent.content ? this.parseJsonSafely(storageEvent.content, null) : void 0,
|
|
10005
|
+
actions: storageEvent.actions ? this.parseJsonSafely(storageEvent.actions, null) : void 0,
|
|
10006
|
+
longRunningToolIds: storageEvent.long_running_tool_ids_json ? new Set(
|
|
10007
|
+
this.parseJsonSafely(storageEvent.long_running_tool_ids_json, [])
|
|
10008
|
+
) : void 0,
|
|
10009
|
+
groundingMetadata: storageEvent.grounding_metadata ? this.parseJsonSafely(storageEvent.grounding_metadata, null) : void 0,
|
|
10010
|
+
partial: storageEvent.partial || void 0,
|
|
10011
|
+
turnComplete: storageEvent.turn_complete || void 0,
|
|
10012
|
+
errorCode: storageEvent.error_code || void 0,
|
|
10013
|
+
errorMessage: storageEvent.error_message || void 0,
|
|
10014
|
+
interrupted: storageEvent.interrupted || void 0
|
|
9712
10015
|
};
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
10016
|
+
return {
|
|
10017
|
+
...baseEvent,
|
|
10018
|
+
// Add any missing required methods from the Event interface
|
|
10019
|
+
isFinalResponse: () => baseEvent.turnComplete === true,
|
|
10020
|
+
getFunctionCalls: () => {
|
|
10021
|
+
if (baseEvent.actions && typeof baseEvent.actions === "object" && "functionCalls" in baseEvent.actions) {
|
|
10022
|
+
return baseEvent.actions.functionCalls || [];
|
|
9717
10023
|
}
|
|
9718
|
-
|
|
9719
|
-
|
|
10024
|
+
return [];
|
|
10025
|
+
},
|
|
10026
|
+
getFunctionResponses: () => {
|
|
10027
|
+
if (baseEvent.actions && typeof baseEvent.actions === "object" && "functionResponses" in baseEvent.actions) {
|
|
10028
|
+
return baseEvent.actions.functionResponses || [];
|
|
9720
10029
|
}
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
10030
|
+
return [];
|
|
10031
|
+
},
|
|
10032
|
+
hasTrailingCodeExecutionResult: () => {
|
|
10033
|
+
if (baseEvent.actions && typeof baseEvent.actions === "object" && "hasTrailingCodeExecutionResult" in baseEvent.actions) {
|
|
10034
|
+
return baseEvent.actions.hasTrailingCodeExecutionResult || false;
|
|
9724
10035
|
}
|
|
9725
|
-
|
|
10036
|
+
return false;
|
|
9726
10037
|
}
|
|
9727
|
-
}
|
|
10038
|
+
};
|
|
9728
10039
|
}
|
|
9729
10040
|
/**
|
|
9730
|
-
*
|
|
10041
|
+
* Updates the session state based on the event.
|
|
10042
|
+
* Overrides the base class method to work with plain object state.
|
|
9731
10043
|
*/
|
|
9732
|
-
|
|
9733
|
-
|
|
9734
|
-
|
|
9735
|
-
|
|
9736
|
-
|
|
9737
|
-
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
10044
|
+
updateSessionState(session, event) {
|
|
10045
|
+
if (!event.actions?.stateDelta) {
|
|
10046
|
+
return;
|
|
10047
|
+
}
|
|
10048
|
+
for (const [key, value] of Object.entries(event.actions.stateDelta)) {
|
|
10049
|
+
if (!key.startsWith("temp_")) {
|
|
10050
|
+
session.state[key] = value;
|
|
10051
|
+
}
|
|
10052
|
+
}
|
|
10053
|
+
}
|
|
10054
|
+
};
|
|
10055
|
+
|
|
10056
|
+
// src/sessions/database-factories.ts
|
|
10057
|
+
import dedent3 from "dedent";
|
|
10058
|
+
import { Kysely, MysqlDialect, PostgresDialect, SqliteDialect } from "kysely";
|
|
10059
|
+
function createDependencyError(packageName, dbType) {
|
|
10060
|
+
return new Error(
|
|
10061
|
+
dedent3`
|
|
10062
|
+
Missing required peer dependency: ${packageName}
|
|
10063
|
+
To use ${dbType} sessions, install the required package:
|
|
10064
|
+
npm install ${packageName}
|
|
10065
|
+
# or
|
|
10066
|
+
pnpm add ${packageName}
|
|
10067
|
+
# or
|
|
10068
|
+
yarn add ${packageName}`
|
|
10069
|
+
);
|
|
10070
|
+
}
|
|
10071
|
+
function createPostgresSessionService(connectionString, options) {
|
|
10072
|
+
let Pool;
|
|
10073
|
+
try {
|
|
10074
|
+
({ Pool } = __require("pg"));
|
|
10075
|
+
} catch (error) {
|
|
10076
|
+
throw createDependencyError("pg", "PostgreSQL");
|
|
10077
|
+
}
|
|
10078
|
+
const db = new Kysely({
|
|
10079
|
+
dialect: new PostgresDialect({
|
|
10080
|
+
pool: new Pool({
|
|
10081
|
+
connectionString,
|
|
10082
|
+
...options
|
|
10083
|
+
})
|
|
10084
|
+
})
|
|
10085
|
+
});
|
|
10086
|
+
return new DatabaseSessionService({ db });
|
|
10087
|
+
}
|
|
10088
|
+
function createMysqlSessionService(connectionString, options) {
|
|
10089
|
+
let createPool;
|
|
10090
|
+
try {
|
|
10091
|
+
({ createPool } = __require("mysql2"));
|
|
10092
|
+
} catch (error) {
|
|
10093
|
+
throw createDependencyError("mysql2", "MySQL");
|
|
10094
|
+
}
|
|
10095
|
+
const db = new Kysely({
|
|
10096
|
+
dialect: new MysqlDialect({
|
|
10097
|
+
pool: createPool({
|
|
10098
|
+
uri: connectionString,
|
|
10099
|
+
...options
|
|
10100
|
+
})
|
|
10101
|
+
})
|
|
10102
|
+
});
|
|
10103
|
+
return new DatabaseSessionService({ db });
|
|
10104
|
+
}
|
|
10105
|
+
function createSqliteSessionService(filename, options) {
|
|
10106
|
+
let Database;
|
|
10107
|
+
try {
|
|
10108
|
+
Database = __require("better-sqlite3");
|
|
10109
|
+
} catch (error) {
|
|
10110
|
+
throw createDependencyError("better-sqlite3", "SQLite");
|
|
10111
|
+
}
|
|
10112
|
+
const db = new Kysely({
|
|
10113
|
+
dialect: new SqliteDialect({
|
|
10114
|
+
database: new Database(filename, options)
|
|
10115
|
+
})
|
|
10116
|
+
});
|
|
10117
|
+
return new DatabaseSessionService({ db });
|
|
10118
|
+
}
|
|
10119
|
+
function createDatabaseSessionService(databaseUrl, options) {
|
|
10120
|
+
if (databaseUrl.startsWith("postgres://") || databaseUrl.startsWith("postgresql://")) {
|
|
10121
|
+
return createPostgresSessionService(databaseUrl, options);
|
|
10122
|
+
}
|
|
10123
|
+
if (databaseUrl.startsWith("mysql://")) {
|
|
10124
|
+
return createMysqlSessionService(databaseUrl, options);
|
|
10125
|
+
}
|
|
10126
|
+
if (databaseUrl.startsWith("sqlite://") || databaseUrl.includes(".db") || databaseUrl === ":memory:") {
|
|
10127
|
+
const filename = databaseUrl.startsWith("sqlite://") ? databaseUrl.substring(9) : databaseUrl;
|
|
10128
|
+
return createSqliteSessionService(filename, options);
|
|
10129
|
+
}
|
|
10130
|
+
throw new Error(`Unsupported database URL: ${databaseUrl}`);
|
|
10131
|
+
}
|
|
10132
|
+
|
|
10133
|
+
// src/artifacts/gcs-artifact-service.ts
|
|
10134
|
+
init_logger();
|
|
10135
|
+
import {
|
|
10136
|
+
Storage
|
|
10137
|
+
} from "@google-cloud/storage";
|
|
10138
|
+
var logger11 = new Logger({ name: "GcsArtifactService" });
|
|
10139
|
+
var GcsArtifactService = class {
|
|
10140
|
+
bucketName;
|
|
10141
|
+
storageClient;
|
|
10142
|
+
bucket;
|
|
10143
|
+
constructor(bucketName, options) {
|
|
10144
|
+
this.bucketName = bucketName;
|
|
10145
|
+
this.storageClient = new Storage(options);
|
|
10146
|
+
this.bucket = this.storageClient.bucket(this.bucketName);
|
|
10147
|
+
}
|
|
10148
|
+
fileHasUserNamespace(filename) {
|
|
10149
|
+
return filename.startsWith("user:");
|
|
10150
|
+
}
|
|
10151
|
+
getBlobName(appName, userId, sessionId, filename, version) {
|
|
10152
|
+
if (this.fileHasUserNamespace(filename)) {
|
|
10153
|
+
return `${appName}/${userId}/user/${filename}/${version}`;
|
|
10154
|
+
}
|
|
10155
|
+
return `${appName}/${userId}/${sessionId}/${filename}/${version}`;
|
|
10156
|
+
}
|
|
10157
|
+
async saveArtifact(args) {
|
|
10158
|
+
const { appName, userId, sessionId, filename, artifact } = args;
|
|
10159
|
+
const versions = await this.listVersions({
|
|
10160
|
+
appName,
|
|
10161
|
+
userId,
|
|
10162
|
+
sessionId,
|
|
10163
|
+
filename
|
|
10164
|
+
});
|
|
10165
|
+
const version = versions.length === 0 ? 0 : Math.max(...versions) + 1;
|
|
10166
|
+
const blobName = this.getBlobName(
|
|
10167
|
+
appName,
|
|
10168
|
+
userId,
|
|
10169
|
+
sessionId,
|
|
10170
|
+
filename,
|
|
10171
|
+
version
|
|
10172
|
+
);
|
|
10173
|
+
const blob = this.bucket.file(blobName);
|
|
10174
|
+
await blob.save(artifact.inlineData.data, {
|
|
10175
|
+
contentType: artifact.inlineData.mimeType,
|
|
10176
|
+
preconditionOpts: { ifGenerationMatch: 0 }
|
|
10177
|
+
});
|
|
10178
|
+
return version;
|
|
10179
|
+
}
|
|
10180
|
+
async loadArtifact(args) {
|
|
10181
|
+
let { version } = args;
|
|
10182
|
+
const { appName, userId, sessionId, filename } = args;
|
|
10183
|
+
if (version === void 0 || version === null) {
|
|
10184
|
+
const versions = await this.listVersions({
|
|
10185
|
+
appName,
|
|
9742
10186
|
userId,
|
|
9743
|
-
sessionId
|
|
9744
|
-
|
|
9745
|
-
if (!session) {
|
|
9746
|
-
throw new Error(`Session not found: ${sessionId}`);
|
|
9747
|
-
}
|
|
9748
|
-
const invocationContext = this._newInvocationContext(session, {
|
|
9749
|
-
newMessage,
|
|
9750
|
-
runConfig
|
|
10187
|
+
sessionId,
|
|
10188
|
+
filename
|
|
9751
10189
|
});
|
|
9752
|
-
if (
|
|
9753
|
-
|
|
9754
|
-
session,
|
|
9755
|
-
newMessage,
|
|
9756
|
-
invocationContext,
|
|
9757
|
-
runConfig.saveInputBlobsAsArtifacts || false
|
|
9758
|
-
);
|
|
10190
|
+
if (versions.length === 0) {
|
|
10191
|
+
return null;
|
|
9759
10192
|
}
|
|
9760
|
-
|
|
9761
|
-
|
|
9762
|
-
|
|
9763
|
-
|
|
9764
|
-
|
|
9765
|
-
|
|
9766
|
-
|
|
9767
|
-
|
|
10193
|
+
version = Math.max(...versions);
|
|
10194
|
+
}
|
|
10195
|
+
const blobName = this.getBlobName(
|
|
10196
|
+
appName,
|
|
10197
|
+
userId,
|
|
10198
|
+
sessionId,
|
|
10199
|
+
filename,
|
|
10200
|
+
version
|
|
10201
|
+
);
|
|
10202
|
+
const blob = this.bucket.file(blobName);
|
|
10203
|
+
try {
|
|
10204
|
+
const [metadata] = await blob.getMetadata();
|
|
10205
|
+
const [artifactBuffer] = await blob.download();
|
|
10206
|
+
if (!artifactBuffer) {
|
|
10207
|
+
return null;
|
|
9768
10208
|
}
|
|
10209
|
+
const part = {
|
|
10210
|
+
inlineData: {
|
|
10211
|
+
data: artifactBuffer.toString(),
|
|
10212
|
+
mimeType: metadata.contentType || "application/octet-stream"
|
|
10213
|
+
}
|
|
10214
|
+
};
|
|
10215
|
+
return part;
|
|
9769
10216
|
} catch (error) {
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
code: SpanStatusCode.ERROR,
|
|
9774
|
-
message: error instanceof Error ? error.message : "Unknown error"
|
|
9775
|
-
});
|
|
10217
|
+
if (error?.code === 404) {
|
|
10218
|
+
return null;
|
|
10219
|
+
}
|
|
9776
10220
|
throw error;
|
|
9777
|
-
} finally {
|
|
9778
|
-
span.end();
|
|
9779
10221
|
}
|
|
9780
10222
|
}
|
|
9781
|
-
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
9786
|
-
|
|
9787
|
-
|
|
9788
|
-
|
|
9789
|
-
|
|
9790
|
-
const part = newMessage.parts[i];
|
|
9791
|
-
if (!part.inlineData) {
|
|
9792
|
-
continue;
|
|
10223
|
+
async listArtifactKeys(args) {
|
|
10224
|
+
const { appName, userId, sessionId } = args;
|
|
10225
|
+
const filenames = /* @__PURE__ */ new Set();
|
|
10226
|
+
const processBlobs = (blobNames) => {
|
|
10227
|
+
for (const name of blobNames) {
|
|
10228
|
+
const parts = name.split("/");
|
|
10229
|
+
if (parts.length === 5) {
|
|
10230
|
+
const filename = parts[3];
|
|
10231
|
+
filenames.add(filename);
|
|
9793
10232
|
}
|
|
9794
|
-
const fileName = `artifact_${invocationContext.invocationId}_${i}`;
|
|
9795
|
-
await this.artifactService.saveArtifact({
|
|
9796
|
-
appName: this.appName,
|
|
9797
|
-
userId: session.userId,
|
|
9798
|
-
sessionId: session.id,
|
|
9799
|
-
filename: fileName,
|
|
9800
|
-
artifact: part
|
|
9801
|
-
});
|
|
9802
|
-
newMessage.parts[i] = {
|
|
9803
|
-
text: `Uploaded file: ${fileName}. It is saved into artifacts`
|
|
9804
|
-
};
|
|
9805
10233
|
}
|
|
9806
|
-
}
|
|
9807
|
-
const userContent = {
|
|
9808
|
-
...newMessage,
|
|
9809
|
-
role: "user"
|
|
9810
|
-
// Ensure role is set for content filtering
|
|
9811
10234
|
};
|
|
9812
|
-
const
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
|
|
9816
|
-
});
|
|
9817
|
-
|
|
10235
|
+
const sessionPrefix = `${appName}/${userId}/${sessionId}/`;
|
|
10236
|
+
const [sessionBlobs] = await this.storageClient.bucket(this.bucketName).getFiles({ prefix: sessionPrefix });
|
|
10237
|
+
processBlobs(sessionBlobs.map((b) => b.name));
|
|
10238
|
+
const userNamespacePrefix = `${appName}/${userId}/user/`;
|
|
10239
|
+
const [userNamespaceBlobs] = await this.storageClient.bucket(this.bucketName).getFiles({ prefix: userNamespacePrefix });
|
|
10240
|
+
processBlobs(userNamespaceBlobs.map((b) => b.name));
|
|
10241
|
+
return Array.from(filenames).sort();
|
|
9818
10242
|
}
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
}
|
|
9827
|
-
const
|
|
9828
|
-
|
|
9829
|
-
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9835
|
-
|
|
9836
|
-
|
|
9837
|
-
|
|
9838
|
-
}
|
|
9839
|
-
if (this._isTransferableAcrossAgentTree(agent)) {
|
|
9840
|
-
return agent;
|
|
9841
|
-
}
|
|
9842
|
-
}
|
|
9843
|
-
return rootAgent;
|
|
10243
|
+
async deleteArtifact(args) {
|
|
10244
|
+
const { appName, userId, sessionId, filename } = args;
|
|
10245
|
+
const versions = await this.listVersions({
|
|
10246
|
+
appName,
|
|
10247
|
+
userId,
|
|
10248
|
+
sessionId,
|
|
10249
|
+
filename
|
|
10250
|
+
});
|
|
10251
|
+
const deletePromises = versions.map((version) => {
|
|
10252
|
+
const blobName = this.getBlobName(
|
|
10253
|
+
appName,
|
|
10254
|
+
userId,
|
|
10255
|
+
sessionId,
|
|
10256
|
+
filename,
|
|
10257
|
+
version
|
|
10258
|
+
);
|
|
10259
|
+
return this.bucket.file(blobName).delete();
|
|
10260
|
+
});
|
|
10261
|
+
await Promise.all(deletePromises);
|
|
9844
10262
|
}
|
|
9845
|
-
|
|
9846
|
-
|
|
9847
|
-
|
|
9848
|
-
|
|
9849
|
-
|
|
9850
|
-
|
|
9851
|
-
|
|
9852
|
-
|
|
9853
|
-
|
|
9854
|
-
|
|
9855
|
-
|
|
10263
|
+
async listVersions(args) {
|
|
10264
|
+
const { appName, userId, sessionId, filename } = args;
|
|
10265
|
+
const prefix = this.getBlobName(appName, userId, sessionId, filename, "");
|
|
10266
|
+
const [blobs] = await this.bucket.getFiles({ prefix });
|
|
10267
|
+
const versions = [];
|
|
10268
|
+
for (const blob of blobs) {
|
|
10269
|
+
const parts = blob.name.split("/");
|
|
10270
|
+
if (parts.length === 5) {
|
|
10271
|
+
const versionStr = parts[4];
|
|
10272
|
+
const versionNum = Number.parseInt(versionStr, 10);
|
|
10273
|
+
if (!Number.isNaN(versionNum)) {
|
|
10274
|
+
versions.push(versionNum);
|
|
10275
|
+
}
|
|
9856
10276
|
}
|
|
9857
|
-
agent = agent.parentAgent || null;
|
|
9858
10277
|
}
|
|
9859
|
-
return
|
|
9860
|
-
}
|
|
9861
|
-
/**
|
|
9862
|
-
* Creates a new invocation context.
|
|
9863
|
-
*/
|
|
9864
|
-
_newInvocationContext(session, {
|
|
9865
|
-
newMessage,
|
|
9866
|
-
runConfig = new RunConfig()
|
|
9867
|
-
}) {
|
|
9868
|
-
const invocationId = newInvocationContextId();
|
|
9869
|
-
return new InvocationContext({
|
|
9870
|
-
artifactService: this.artifactService,
|
|
9871
|
-
sessionService: this.sessionService,
|
|
9872
|
-
memoryService: this.memoryService,
|
|
9873
|
-
invocationId,
|
|
9874
|
-
agent: this.agent,
|
|
9875
|
-
session,
|
|
9876
|
-
userContent: newMessage || null,
|
|
9877
|
-
liveRequestQueue: null,
|
|
9878
|
-
runConfig
|
|
9879
|
-
});
|
|
9880
|
-
}
|
|
9881
|
-
};
|
|
9882
|
-
var InMemoryRunner = class extends Runner {
|
|
9883
|
-
/**
|
|
9884
|
-
* Deprecated. Please don't use. The in-memory session service for the runner.
|
|
9885
|
-
*/
|
|
9886
|
-
_inMemorySessionService;
|
|
9887
|
-
/**
|
|
9888
|
-
* Initializes the InMemoryRunner.
|
|
9889
|
-
*/
|
|
9890
|
-
constructor(agent, { appName = "InMemoryRunner" } = {}) {
|
|
9891
|
-
const inMemorySessionService = new InMemorySessionService();
|
|
9892
|
-
super({
|
|
9893
|
-
appName,
|
|
9894
|
-
agent,
|
|
9895
|
-
artifactService: new InMemoryArtifactService(),
|
|
9896
|
-
sessionService: inMemorySessionService,
|
|
9897
|
-
memoryService: new InMemoryMemoryService()
|
|
9898
|
-
});
|
|
9899
|
-
this._inMemorySessionService = inMemorySessionService;
|
|
10278
|
+
return versions.sort((a, b) => a - b);
|
|
9900
10279
|
}
|
|
9901
10280
|
};
|
|
9902
10281
|
|
|
10282
|
+
// src/flows/index.ts
|
|
10283
|
+
var flows_exports = {};
|
|
10284
|
+
__export(flows_exports, {
|
|
10285
|
+
AF_FUNCTION_CALL_ID_PREFIX: () => AF_FUNCTION_CALL_ID_PREFIX,
|
|
10286
|
+
AutoFlow: () => AutoFlow,
|
|
10287
|
+
BaseLlmFlow: () => BaseLlmFlow,
|
|
10288
|
+
BaseLlmRequestProcessor: () => BaseLlmRequestProcessor,
|
|
10289
|
+
BaseLlmResponseProcessor: () => BaseLlmResponseProcessor,
|
|
10290
|
+
REQUEST_EUC_FUNCTION_CALL_NAME: () => REQUEST_EUC_FUNCTION_CALL_NAME,
|
|
10291
|
+
SingleFlow: () => SingleFlow,
|
|
10292
|
+
agentTransferRequestProcessor: () => requestProcessor8,
|
|
10293
|
+
basicRequestProcessor: () => requestProcessor,
|
|
10294
|
+
codeExecutionRequestProcessor: () => requestProcessor7,
|
|
10295
|
+
codeExecutionResponseProcessor: () => responseProcessor2,
|
|
10296
|
+
contentRequestProcessor: () => requestProcessor5,
|
|
10297
|
+
generateAuthEvent: () => generateAuthEvent,
|
|
10298
|
+
generateClientFunctionCallId: () => generateClientFunctionCallId,
|
|
10299
|
+
getLongRunningFunctionCalls: () => getLongRunningFunctionCalls,
|
|
10300
|
+
handleFunctionCallsAsync: () => handleFunctionCallsAsync,
|
|
10301
|
+
handleFunctionCallsLive: () => handleFunctionCallsLive,
|
|
10302
|
+
identityRequestProcessor: () => requestProcessor3,
|
|
10303
|
+
instructionsRequestProcessor: () => requestProcessor4,
|
|
10304
|
+
mergeParallelFunctionResponseEvents: () => mergeParallelFunctionResponseEvents,
|
|
10305
|
+
nlPlanningRequestProcessor: () => requestProcessor6,
|
|
10306
|
+
nlPlanningResponseProcessor: () => responseProcessor,
|
|
10307
|
+
populateClientFunctionCallId: () => populateClientFunctionCallId,
|
|
10308
|
+
removeClientFunctionCallId: () => removeClientFunctionCallId
|
|
10309
|
+
});
|
|
10310
|
+
|
|
9903
10311
|
// src/version.ts
|
|
9904
10312
|
var VERSION = "0.1.0";
|
|
9905
10313
|
export {
|
|
9906
10314
|
AF_FUNCTION_CALL_ID_PREFIX,
|
|
9907
10315
|
LlmAgent as Agent,
|
|
10316
|
+
AgentBuilder,
|
|
9908
10317
|
agents_exports as Agents,
|
|
9909
10318
|
AnthropicLlm,
|
|
9910
10319
|
ApiKeyCredential,
|
|
@@ -9959,9 +10368,21 @@ export {
|
|
|
9959
10368
|
LoadArtifactsTool,
|
|
9960
10369
|
LoadMemoryTool,
|
|
9961
10370
|
LoopAgent,
|
|
10371
|
+
McpAbi,
|
|
10372
|
+
McpAtp,
|
|
10373
|
+
McpBamm,
|
|
9962
10374
|
McpError,
|
|
9963
10375
|
McpErrorType,
|
|
10376
|
+
McpFilesystem,
|
|
10377
|
+
McpFraxlend,
|
|
10378
|
+
McpGeneric,
|
|
10379
|
+
McpIqWiki,
|
|
10380
|
+
McpMemory,
|
|
10381
|
+
McpNearAgent,
|
|
10382
|
+
McpNearIntentSwaps,
|
|
10383
|
+
McpOdos,
|
|
9964
10384
|
McpSamplingHandler,
|
|
10385
|
+
McpTelegram,
|
|
9965
10386
|
McpToolset,
|
|
9966
10387
|
memory_exports as Memory,
|
|
9967
10388
|
models_exports as Models,
|