Skip to content

Commit 3ed0bbf

Browse files
authored
Merge pull request #1441 from refly-ai/feat/tool_call_status
feat(tool-call): implement tool call management and enhance action de…
2 parents e5e3716 + 268b9a0 commit 3ed0bbf

File tree

27 files changed

+1958
-328
lines changed

27 files changed

+1958
-328
lines changed

.vscode/launch.json

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,27 @@
77
{
88
"type": "node",
99
"request": "launch",
10-
"name": "Launch Program",
11-
"skipFiles": ["<node_internals>/**"],
12-
"program": "${file}",
13-
"outFiles": ["${workspaceFolder}/**/*.js"]
10+
"name": "Launch API (debug)",
11+
"runtimeExecutable": "pnpm",
12+
"runtimeArgs": ["--filter", "api", "dev"],
13+
"cwd": "${workspaceFolder}",
14+
"console": "integratedTerminal",
15+
"env": {
16+
"NODE_OPTIONS": "--inspect=0.0.0.0:9229"
17+
},
18+
"autoAttachChildProcesses": true,
19+
"skipFiles": ["<node_internals>/**"]
20+
},
21+
{
22+
"type": "node",
23+
"request": "attach",
24+
"name": "Attach to API",
25+
"port": 9229,
26+
"address": "localhost",
27+
"restart": false,
28+
"localRoot": "${workspaceFolder}",
29+
"remoteRoot": "${workspaceFolder}",
30+
"skipFiles": ["<node_internals>/**"]
1431
}
1532
]
1633
}

apps/api/prisma/schema.prisma

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,19 +1528,28 @@ model Toolset {
15281528

15291529
model ToolCallResult {
15301530
/// Primary key
1531-
pk Int @id @default(autoincrement())
1531+
pk Int @id @default(autoincrement())
1532+
/// Result ID
1533+
resultId String @map("result_id")
1534+
/// Result version
1535+
version Int @default(0) @map("version")
15321536
/// Call ID
1533-
callId String @unique @map("call_id")
1537+
callId String @unique @map("call_id")
15341538
/// UID
1535-
uid String @map("uid")
1539+
uid String @map("uid")
15361540
/// Toolset ID
1537-
toolsetId String @map("toolset_id")
1541+
toolsetId String @map("toolset_id")
15381542
/// Tool name
1539-
toolName String @map("tool_name")
1543+
toolName String @map("tool_name")
1544+
/// Step name
1545+
stepName String? @map("step_name")
15401546
/// Input data
1541-
input String @map("input")
1547+
input String @map("input")
15421548
/// Output data
1543-
output String @map("output")
1549+
output String @map("output")
1550+
1551+
/// Status: enum
1552+
status String @default("executing") @map("status")
15441553
/// Error message
15451554
error String? @map("error")
15461555
/// Create timestamp
@@ -1550,6 +1559,7 @@ model ToolCallResult {
15501559
/// Deletion timestamp
15511560
deletedAt DateTime? @map("deleted_at") @db.Timestamptz()
15521561
1562+
@@index([resultId, version])
15531563
@@index([toolsetId, deletedAt])
15541564
@@index([toolName, deletedAt])
15551565
@@map("tool_call_results")

apps/api/src/modules/action/action.dto.ts

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,48 @@ import {
66
EntityType,
77
ModelInfo,
88
ModelTier,
9+
ToolCallResult,
910
} from '@refly/openapi-schema';
1011
import {
1112
ActionResult as ActionResultModel,
1213
ActionStep as ActionStepModel,
14+
ToolCallResult as ToolCallResultModel,
1315
} from '../../generated/client';
1416
import { pick, safeParseJSON } from '@refly/utils';
1517

18+
type ActionStepDetail = ActionStepModel & {
19+
toolCalls?: ToolCallResultModel[];
20+
};
21+
1622
export type ActionDetail = ActionResultModel & {
17-
steps?: ActionStepModel[];
23+
steps?: ActionStepDetail[];
1824
modelInfo?: ModelInfo;
1925
};
2026

21-
export function actionStepPO2DTO(step: ActionStepModel): ActionStep {
27+
export function actionStepPO2DTO(step: ActionStepDetail): ActionStep {
2228
return {
2329
...pick(step, ['name', 'content', 'reasoningContent']),
2430
logs: safeParseJSON(step.logs || '[]'),
2531
artifacts: safeParseJSON(step.artifacts || '[]'),
2632
structuredData: safeParseJSON(step.structuredData || '{}'),
2733
tokenUsage: safeParseJSON(step.tokenUsage || '[]'),
34+
toolCalls: step.toolCalls?.map(toolCallResultPO2DTO),
35+
};
36+
}
37+
38+
export function toolCallResultPO2DTO(toolCall: ToolCallResultModel): ToolCallResult {
39+
return {
40+
callId: toolCall.callId,
41+
uid: toolCall.uid,
42+
toolsetId: toolCall.toolsetId,
43+
toolName: toolCall.toolName,
44+
input: safeParseJSON(toolCall.input || '{}'),
45+
output: safeParseJSON(toolCall.output || '{}'),
46+
error: toolCall.error || '',
47+
status: toolCall.status as 'executing' | 'completed' | 'failed',
48+
createdAt: toolCall.createdAt.getTime(),
49+
updatedAt: toolCall.updatedAt.getTime(),
50+
deletedAt: toolCall.deletedAt?.getTime(),
2851
};
2952
}
3053

apps/api/src/modules/action/action.module.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { Module, forwardRef } from '@nestjs/common';
2-
import { ActionController } from './action.controller';
3-
import { ActionService } from './action.service';
42
import { CommonModule } from '../common/common.module';
53
import { ProviderModule } from '../provider/provider.module';
64
import { SkillModule } from '../skill/skill.module';
5+
import { ToolCallModule } from '../tool-call/tool-call.module';
6+
import { ActionController } from './action.controller';
7+
import { ActionService } from './action.service';
78

89
@Module({
9-
imports: [CommonModule, ProviderModule, forwardRef(() => SkillModule)],
10+
imports: [CommonModule, ProviderModule, ToolCallModule, forwardRef(() => SkillModule)],
1011
controllers: [ActionController],
1112
providers: [ActionService],
1213
exports: [ActionService],

apps/api/src/modules/action/action.service.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import { ActionDetail } from '../action/action.dto';
2-
import { PrismaService } from '../common/prisma.service';
31
import { Injectable, Logger } from '@nestjs/common';
42
import { ActionResultNotFoundError } from '@refly/errors';
5-
import { ActionResult } from '../../generated/client';
63
import { AbortActionRequest, EntityType, GetActionResultData, User } from '@refly/openapi-schema';
74
import { batchReplaceRegex, genActionResultID, pick } from '@refly/utils';
85
import pLimit from 'p-limit';
9-
import { ProviderService } from '../provider/provider.service';
6+
import { ActionResult } from '../../generated/client';
7+
import { ActionDetail } from '../action/action.dto';
8+
import { PrismaService } from '../common/prisma.service';
109
import { providerItem2ModelInfo } from '../provider/provider.dto';
10+
import { ProviderService } from '../provider/provider.service';
11+
import { ToolCallService } from '../tool-call/tool-call.service';
1112

1213
@Injectable()
1314
export class ActionService {
@@ -22,6 +23,7 @@ export class ActionService {
2223
constructor(
2324
private readonly prisma: PrismaService,
2425
private readonly providerService: ProviderService,
26+
private readonly toolCallService: ToolCallService,
2527
) {}
2628

2729
async getActionResult(user: User, param: GetActionResultData['query']): Promise<ActionDetail> {
@@ -58,7 +60,12 @@ export class ActionService {
5860
orderBy: { order: 'asc' },
5961
});
6062

61-
return { ...result, steps, modelInfo };
63+
const toolCalls = await this.toolCallService.fetchToolCalls(result.resultId, result.version);
64+
const toolCallsByStep = this.toolCallService.groupToolCallsByStep(steps, toolCalls);
65+
const stepsWithToolCalls = this.toolCallService.attachToolCallsToSteps(steps, toolCallsByStep);
66+
await this.toolCallService.deriveAndUpdateActionStatus(result, toolCalls);
67+
68+
return { ...result, steps: stepsWithToolCalls, modelInfo };
6269
}
6370

6471
async duplicateActionResults(

0 commit comments

Comments
 (0)