Skip to content

Commit f6e8a24

Browse files
committed
fix: apply review changes
1 parent bcf01cc commit f6e8a24

File tree

9 files changed

+237
-204
lines changed

9 files changed

+237
-204
lines changed

agent-manager/prisma/schema.prisma

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ model Agent {
2626
triggers Trigger[] // One-to-many relationship with Trigger
2727
template Template? @relation(fields: [template_id], references: [id], onDelete: SetNull, onUpdate: Cascade)
2828
secret_key Bytes @db.ByteA
29+
config Json?
2930
}
3031

3132
model Trigger {

agent-node/src/executor/AgentRunner.ts

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { HdWallet } from 'libcardano'
88
import { AgentWalletDetails } from '../types/types'
99
import { globalState } from '../constants/global'
1010
import { EventContext } from './BaseFunction'
11-
import { LLMService } from '../service/LLMService'
1211

1312
export class AgentRunner {
1413
executor: Executor
@@ -20,60 +19,6 @@ export class AgentRunner {
2019
}
2120

2221
async invokeFunction(triggerType: TriggerType, instanceIndex: number, method: string, ...args: any) {
23-
const extractedArgs = this.extractArgumentValues(args)
24-
const shouldUseLLM = this.shouldUseLLMForFunction(method)
25-
26-
if (shouldUseLLM) {
27-
console.log('[AgentRunner] LLM gating enabled for', method)
28-
console.log(
29-
'[AgentRunner] GEMINI_API_KEY present:',
30-
!!process.env.GEMINI_API_KEY || !!process.env.GOOGLE_API_KEY
31-
)
32-
try {
33-
const llm = new LLMService()
34-
console.log(
35-
'[AgentRunner] functionLLMSettings:',
36-
JSON.stringify(globalState.functionLLMSettings, null, 2)
37-
)
38-
const userPrefText = this.getUserPreferenceText(method)
39-
console.log(
40-
'[AgentRunner] user policy for',
41-
method,
42-
':',
43-
userPrefText || '(empty)'
44-
)
45-
const structuredPrefs = {}
46-
const decision = await llm.shouldExecuteFunction(
47-
method,
48-
extractedArgs,
49-
structuredPrefs,
50-
userPrefText,
51-
globalState.systemPrompt
52-
)
53-
if (!decision.should_execute) {
54-
const blocked = [
55-
{
56-
function: method,
57-
arguments: args,
58-
return: {
59-
operation: method,
60-
executed: false,
61-
blocked_by_llm: true,
62-
llm_reasoning: decision.reasoning,
63-
llm_confidence: decision.confidence,
64-
message: `LLM blocked: ${decision.reasoning}`,
65-
timestamp: new Date().toISOString(),
66-
},
67-
},
68-
]
69-
saveTxLog(blocked, this.managerInterface, triggerType, instanceIndex)
70-
return
71-
}
72-
} catch (e) {
73-
console.error(`LLM gating failed, continuing: ${e}`)
74-
}
75-
}
76-
7722
this.executor.invokeFunction(method, ...args).then((result) => {
7823
saveTxLog(result, this.managerInterface, triggerType, instanceIndex)
7924
})
@@ -102,27 +47,6 @@ export class AgentRunner {
10247
})
10348
}
10449
}
105-
106-
// LLM helpers
107-
private shouldUseLLMForFunction(method: string): boolean {
108-
const fnCfg = globalState.functionLLMSettings?.[method]
109-
console.log('fncfg is', fnCfg)
110-
return !!(fnCfg && fnCfg.enabled)
111-
}
112-
113-
private getUserPreferenceText(method: string): string {
114-
console.log(
115-
`globalState function llm settings -> ${JSON.stringify(
116-
globalState.functionLLMSettings || {}
117-
)}`
118-
)
119-
return globalState.functionLLMSettings?.[method]?.userPrefText || ''
120-
}
121-
122-
private extractArgumentValues(args: any[]) {
123-
return args.map((a) => (a && typeof a === 'object' && 'value' in a ? a.value : a))
124-
}
125-
12650

12751
async remakeContext(index: number) {
12852
const rootKey = loadRootKeyFromBuffer()
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { TriggerType } from '../service/triggerService'
2+
import { saveTxLog } from '../utils/agent'
3+
import { globalState } from '../constants/global'
4+
import { LLMService } from '../service/LLMService'
5+
import { EventContext } from './BaseFunction'
6+
import { AgentRunner } from './AgentRunner'
7+
8+
export class LLMGatedRunner {
9+
constructor(private readonly core: AgentRunner) {}
10+
11+
async invokeFunction(triggerType: TriggerType, instanceIndex: number, method: string, ...args: any) {
12+
const extractedArgs = this.extractArgumentValues(args)
13+
const shouldGate = this.shouldUseLLMForFunction(method) && this.isCron(triggerType)
14+
if (shouldGate) {
15+
try {
16+
const llm = new LLMService()
17+
const decision = await llm.shouldExecuteFunction(
18+
method,
19+
extractedArgs,
20+
{},
21+
this.getUserPreferenceText(method),
22+
this.getSystemPrompt()
23+
)
24+
if (!decision.should_execute) {
25+
const blocked = [
26+
{
27+
function: method,
28+
arguments: args,
29+
return: {
30+
operation: method,
31+
executed: false,
32+
blocked_by_llm: true,
33+
llm_reasoning: decision.reasoning,
34+
llm_confidence: decision.confidence,
35+
message: `LLM blocked: ${decision.reasoning}`,
36+
timestamp: new Date().toISOString(),
37+
},
38+
},
39+
]
40+
saveTxLog(blocked, (this.core as any).managerInterface, triggerType, instanceIndex)
41+
return
42+
}
43+
} catch (e) {
44+
console.error(`LLM gating failed, continuing: ${e}`)
45+
}
46+
}
47+
return this.core.invokeFunction(triggerType, instanceIndex, method, ...args)
48+
}
49+
50+
async invokeFunctionWithEventContext(
51+
eventFilterContext: any,
52+
context: EventContext,
53+
triggerType: TriggerType,
54+
instanceIndex: number,
55+
method: string,
56+
parameters: any[]
57+
) {
58+
return this.core.invokeFunctionWithEventContext(
59+
eventFilterContext,
60+
context,
61+
triggerType,
62+
instanceIndex,
63+
method,
64+
parameters
65+
)
66+
}
67+
68+
async remakeContext(index: number) {
69+
return this.core.remakeContext(index)
70+
}
71+
72+
// helpers
73+
private isCron(triggerType: TriggerType): boolean {
74+
return String(triggerType) === 'CRON'
75+
}
76+
private shouldUseLLMForFunction(method: string): boolean {
77+
const fnCfg = globalState.functionLLMSettings?.[method]
78+
return !!(fnCfg && fnCfg.enabled)
79+
}
80+
private getUserPreferenceText(method: string): string {
81+
return globalState.functionLLMSettings?.[method]?.userPrefText || ''
82+
}
83+
private getSystemPrompt(): string {
84+
return (globalState.systemPrompt ?? '').toString()
85+
}
86+
private extractArgumentValues(args: any[]) {
87+
return args.map((a) => (a && typeof a === 'object' && 'value' in a ? a.value : a))
88+
}
89+
}

agent-node/src/index.ts

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { AgentRunner } from './executor/AgentRunner'
1414
import { decodeBase64string } from './utils/base64converter'
1515
import { validateToken } from './utils/validator'
1616
import { getHandlers } from './executor/AgentFunctions'
17+
import { LLMGatedRunner } from './executor/LlmGatedRunner'
1718

1819
configDotenv()
1920
let wsUrl: string = process.env.WS_URL as string
@@ -62,7 +63,7 @@ function connectToManagerWebSocket() {
6263
const managerInterface = new ManagerInterface(rpcChannel)
6364
const txListener = new TxListener()
6465

65-
const agentRunners: Array<AgentRunner> = []
66+
const agentRunners: Array<any> = []
6667

6768
rpcChannel.on('methodCall', (method, args) => {
6869
agentRunners.forEach((runner, index) => {
@@ -72,11 +73,8 @@ function connectToManagerWebSocket() {
7273

7374
const topicHandler = new RpcTopicHandler(managerInterface, txListener)
7475

75-
// LLM settings extractor from configurations
76+
// LLM settings extractor from configurations
7677
function applyFnSettingsFromConfigurations(message: any) {
77-
try {
78-
console.log('[INIT] Raw configurations:', JSON.stringify(message?.configurations, null, 2))
79-
} catch {}
8078
if (!message?.configurations) return
8179
globalState.functionLLMSettings = {}
8280
message.configurations.forEach((cfg: any) => {
@@ -92,46 +90,40 @@ function connectToManagerWebSocket() {
9290
console.log('[INIT] LLM settings for:', Object.keys(globalState.functionLLMSettings))
9391
}
9492

93+
// loads the system prompt
94+
function applySystemPromptFromMessage(message: any, logCtx: string) {
95+
const prompt = message?.agentConfig?.system_prompt ?? message?.config?.system_prompt
96+
97+
if (typeof prompt === 'string' && prompt.length && prompt !== globalState.systemPrompt) {
98+
globalState.systemPrompt = prompt
99+
}
100+
}
101+
95102
rpcChannel.on('event', (topic, message) => {
96103
// initial payload containing configs
97104
if (topic === 'initial_config') {
98-
if (message.agentConfig?.system_prompt) {
99-
globalState.systemPrompt = message.agentConfig.system_prompt
100-
console.log('[INIT] System prompt loaded')
101-
}
105+
applySystemPromptFromMessage(message, 'initial_config')
102106
applyFnSettingsFromConfigurations(message)
103107
return
104108
}
105109

106-
// config updates from manager
110+
// config updates from manager
107111
if (topic === 'config_updated') {
108112
applyFnSettingsFromConfigurations(message)
109-
if (message.agentConfig?.system_prompt) {
110-
globalState.systemPrompt = message.agentConfig.system_prompt
111-
console.log('[INIT] System prompt loaded')
112-
}
113+
applySystemPromptFromMessage(message, 'initial_config')
113114
}
114115

115116
if (topic == 'instance_count') {
116-
// load system prompt if present
117-
if (message.agentConfig?.system_prompt) {
118-
globalState.systemPrompt = message.agentConfig.system_prompt
119-
console.log('[INIT] System prompt loaded')
120-
}
121-
if (message.config?.system_prompt) {
122-
globalState.systemPrompt = message.config.system_prompt
123-
console.log('Loaded system prompt:', globalState.systemPrompt.slice(0, 80) + '...')
124-
}
125-
126-
// ensure LLM prefs set
117+
applySystemPromptFromMessage(message, 'initial_config')
127118
applyFnSettingsFromConfigurations(message)
128-
119+
129120
globalRootKeyBuffer.value = message.rootKeyBuffer
130121
globalState.agentName = message.agentName
131122
Array(message.instanceCount)
132123
.fill('')
133124
.forEach(async (item, index) => {
134-
const runner = new AgentRunner(managerInterface, txListener)
125+
const coreRunner = new AgentRunner(managerInterface, txListener)
126+
const runner = new LLMGatedRunner(coreRunner)
135127
await runner.remakeContext(index)
136128
agentRunners.push(runner)
137129
})

0 commit comments

Comments
 (0)