@dotsetlabs/dotclaw 1.2.0 → 1.4.0
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/README.md +9 -0
- package/config-examples/runtime.json +119 -2
- package/container/agent-runner/src/agent-config.ts +20 -2
- package/container/agent-runner/src/container-protocol.ts +11 -0
- package/container/agent-runner/src/index.ts +39 -7
- package/container/agent-runner/src/tools.ts +84 -5
- package/dist/agent-context.d.ts +5 -0
- package/dist/agent-context.d.ts.map +1 -1
- package/dist/agent-context.js +19 -8
- package/dist/agent-context.js.map +1 -1
- package/dist/agent-execution.d.ts +6 -0
- package/dist/agent-execution.d.ts.map +1 -1
- package/dist/agent-execution.js +61 -4
- package/dist/agent-execution.js.map +1 -1
- package/dist/background-job-classifier.d.ts +20 -0
- package/dist/background-job-classifier.d.ts.map +1 -0
- package/dist/background-job-classifier.js +145 -0
- package/dist/background-job-classifier.js.map +1 -0
- package/dist/background-jobs.d.ts.map +1 -1
- package/dist/background-jobs.js +81 -4
- package/dist/background-jobs.js.map +1 -1
- package/dist/cli.js +343 -11
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +0 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +0 -3
- package/dist/config.js.map +1 -1
- package/dist/container-protocol.d.ts +11 -0
- package/dist/container-protocol.d.ts.map +1 -1
- package/dist/container-runner.d.ts.map +1 -1
- package/dist/container-runner.js +9 -1
- package/dist/container-runner.js.map +1 -1
- package/dist/dashboard.d.ts +5 -0
- package/dist/dashboard.d.ts.map +1 -1
- package/dist/dashboard.js +58 -8
- package/dist/dashboard.js.map +1 -1
- package/dist/db.d.ts +16 -0
- package/dist/db.d.ts.map +1 -1
- package/dist/db.js +53 -0
- package/dist/db.js.map +1 -1
- package/dist/index.js +403 -30
- package/dist/index.js.map +1 -1
- package/dist/json-helpers.d.ts +6 -0
- package/dist/json-helpers.d.ts.map +1 -0
- package/dist/json-helpers.js +17 -0
- package/dist/json-helpers.js.map +1 -0
- package/dist/logger.d.ts +0 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +1 -1
- package/dist/logger.js.map +1 -1
- package/dist/metrics.d.ts +3 -0
- package/dist/metrics.d.ts.map +1 -1
- package/dist/metrics.js +35 -1
- package/dist/metrics.js.map +1 -1
- package/dist/planner-probe.d.ts +14 -0
- package/dist/planner-probe.d.ts.map +1 -0
- package/dist/planner-probe.js +97 -0
- package/dist/planner-probe.js.map +1 -0
- package/dist/progress.d.ts +27 -0
- package/dist/progress.d.ts.map +1 -1
- package/dist/progress.js +151 -0
- package/dist/progress.js.map +1 -1
- package/dist/request-router.d.ts +34 -0
- package/dist/request-router.d.ts.map +1 -0
- package/dist/request-router.js +148 -0
- package/dist/request-router.js.map +1 -0
- package/dist/runtime-config.d.ts +81 -0
- package/dist/runtime-config.d.ts.map +1 -1
- package/dist/runtime-config.js +190 -13
- package/dist/runtime-config.js.map +1 -1
- package/dist/task-scheduler.d.ts.map +1 -1
- package/dist/task-scheduler.js +56 -9
- package/dist/task-scheduler.js.map +1 -1
- package/dist/trace-writer.d.ts +1 -0
- package/dist/trace-writer.d.ts.map +1 -1
- package/dist/trace-writer.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,6 +45,8 @@ After installation, use the `dotclaw` CLI:
|
|
|
45
45
|
```bash
|
|
46
46
|
dotclaw setup # Full setup (init + configure + build + install service)
|
|
47
47
|
dotclaw configure # Re-configure API keys and model
|
|
48
|
+
dotclaw add-instance # Create and start an isolated instance
|
|
49
|
+
dotclaw instances # List discovered instances
|
|
48
50
|
dotclaw build # Build the Docker container image
|
|
49
51
|
dotclaw start # Start the service
|
|
50
52
|
dotclaw stop # Stop the service
|
|
@@ -55,6 +57,13 @@ dotclaw doctor # Run diagnostics
|
|
|
55
57
|
dotclaw register # Register a new Telegram chat
|
|
56
58
|
```
|
|
57
59
|
|
|
60
|
+
Instance flags:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
dotclaw status --id dev # Run against a specific instance (~/.dotclaw-dev)
|
|
64
|
+
dotclaw restart --all # Restart all instances
|
|
65
|
+
```
|
|
66
|
+
|
|
58
67
|
## Configuration
|
|
59
68
|
|
|
60
69
|
All configuration and data is stored in `~/.dotclaw/`:
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
"host": {
|
|
3
3
|
"logLevel": "info",
|
|
4
4
|
"container": {
|
|
5
|
-
"mode": "daemon"
|
|
5
|
+
"mode": "daemon",
|
|
6
|
+
"instanceId": ""
|
|
6
7
|
},
|
|
7
8
|
"metrics": {
|
|
8
9
|
"port": 3001,
|
|
@@ -19,7 +20,109 @@
|
|
|
19
20
|
"backgroundJobs": {
|
|
20
21
|
"enabled": true,
|
|
21
22
|
"maxConcurrent": 2,
|
|
22
|
-
"maxRuntimeMs": 2400000
|
|
23
|
+
"maxRuntimeMs": 2400000,
|
|
24
|
+
"progress": {
|
|
25
|
+
"enabled": true,
|
|
26
|
+
"startDelayMs": 30000,
|
|
27
|
+
"intervalMs": 120000,
|
|
28
|
+
"maxUpdates": 3
|
|
29
|
+
},
|
|
30
|
+
"autoSpawn": {
|
|
31
|
+
"enabled": true,
|
|
32
|
+
"foregroundTimeoutMs": 90000,
|
|
33
|
+
"onTimeout": true,
|
|
34
|
+
"onToolLimit": true,
|
|
35
|
+
"classifier": {
|
|
36
|
+
"enabled": true,
|
|
37
|
+
"model": "openai/gpt-5-nano",
|
|
38
|
+
"timeoutMs": 3000,
|
|
39
|
+
"maxOutputTokens": 32,
|
|
40
|
+
"temperature": 0,
|
|
41
|
+
"confidenceThreshold": 0.6,
|
|
42
|
+
"adaptive": {
|
|
43
|
+
"enabled": true,
|
|
44
|
+
"minThreshold": 0.55,
|
|
45
|
+
"maxThreshold": 0.65,
|
|
46
|
+
"queueDepthLow": 0,
|
|
47
|
+
"queueDepthHigh": 4
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"routing": {
|
|
53
|
+
"enabled": true,
|
|
54
|
+
"maxFastChars": 200,
|
|
55
|
+
"maxStandardChars": 1200,
|
|
56
|
+
"backgroundMinChars": 2000,
|
|
57
|
+
"fastKeywords": ["hi", "hello", "hey", "who are you", "what can you do"],
|
|
58
|
+
"deepKeywords": ["research", "analysis", "report", "dashboard", "refactor", "architecture", "design"],
|
|
59
|
+
"backgroundKeywords": ["background", "long-running", "research", "dashboard", "refactor", "report"],
|
|
60
|
+
"classifierFallback": {
|
|
61
|
+
"enabled": true,
|
|
62
|
+
"minChars": 600
|
|
63
|
+
},
|
|
64
|
+
"plannerProbe": {
|
|
65
|
+
"enabled": true,
|
|
66
|
+
"model": "openai/gpt-5-nano",
|
|
67
|
+
"timeoutMs": 3000,
|
|
68
|
+
"maxOutputTokens": 120,
|
|
69
|
+
"temperature": 0,
|
|
70
|
+
"minChars": 700,
|
|
71
|
+
"minSteps": 4,
|
|
72
|
+
"minTools": 3
|
|
73
|
+
},
|
|
74
|
+
"profiles": {
|
|
75
|
+
"fast": {
|
|
76
|
+
"model": "openai/gpt-5-nano",
|
|
77
|
+
"maxOutputTokens": 256,
|
|
78
|
+
"maxToolSteps": 6,
|
|
79
|
+
"recallMaxResults": 0,
|
|
80
|
+
"recallMaxTokens": 0,
|
|
81
|
+
"enablePlanner": false,
|
|
82
|
+
"enableValidation": false,
|
|
83
|
+
"responseValidationMaxRetries": 0,
|
|
84
|
+
"enableMemoryRecall": false,
|
|
85
|
+
"enableMemoryExtraction": false,
|
|
86
|
+
"progress": { "enabled": false }
|
|
87
|
+
},
|
|
88
|
+
"standard": {
|
|
89
|
+
"model": "openai/gpt-5-mini",
|
|
90
|
+
"maxOutputTokens": 768,
|
|
91
|
+
"maxToolSteps": 16,
|
|
92
|
+
"recallMaxResults": 6,
|
|
93
|
+
"recallMaxTokens": 1500,
|
|
94
|
+
"enablePlanner": true,
|
|
95
|
+
"enableValidation": true,
|
|
96
|
+
"responseValidationMaxRetries": 1,
|
|
97
|
+
"enableMemoryRecall": true,
|
|
98
|
+
"enableMemoryExtraction": true
|
|
99
|
+
},
|
|
100
|
+
"deep": {
|
|
101
|
+
"model": "moonshotai/kimi-k2.5",
|
|
102
|
+
"maxOutputTokens": 1536,
|
|
103
|
+
"maxToolSteps": 32,
|
|
104
|
+
"recallMaxResults": 12,
|
|
105
|
+
"recallMaxTokens": 2500,
|
|
106
|
+
"enablePlanner": true,
|
|
107
|
+
"enableValidation": true,
|
|
108
|
+
"responseValidationMaxRetries": 2,
|
|
109
|
+
"enableMemoryRecall": true,
|
|
110
|
+
"enableMemoryExtraction": true
|
|
111
|
+
},
|
|
112
|
+
"background": {
|
|
113
|
+
"model": "moonshotai/kimi-k2.5",
|
|
114
|
+
"maxOutputTokens": 2048,
|
|
115
|
+
"maxToolSteps": 64,
|
|
116
|
+
"recallMaxResults": 16,
|
|
117
|
+
"recallMaxTokens": 4000,
|
|
118
|
+
"enablePlanner": true,
|
|
119
|
+
"enableValidation": true,
|
|
120
|
+
"responseValidationMaxRetries": 2,
|
|
121
|
+
"enableMemoryRecall": true,
|
|
122
|
+
"enableMemoryExtraction": true,
|
|
123
|
+
"progress": { "enabled": true, "initialMs": 15000, "intervalMs": 60000, "maxUpdates": 3 }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
23
126
|
}
|
|
24
127
|
},
|
|
25
128
|
"agent": {
|
|
@@ -30,6 +133,20 @@
|
|
|
30
133
|
"planner": {
|
|
31
134
|
"enabled": true,
|
|
32
135
|
"mode": "auto"
|
|
136
|
+
},
|
|
137
|
+
"responseValidation": {
|
|
138
|
+
"enabled": true,
|
|
139
|
+
"minPromptTokens": 400,
|
|
140
|
+
"minResponseTokens": 160
|
|
141
|
+
},
|
|
142
|
+
"tools": {
|
|
143
|
+
"progress": {
|
|
144
|
+
"enabled": true,
|
|
145
|
+
"minIntervalMs": 30000,
|
|
146
|
+
"notifyTools": ["WebSearch", "WebFetch", "Bash", "GitClone", "NpmInstall"],
|
|
147
|
+
"notifyOnStart": true,
|
|
148
|
+
"notifyOnError": true
|
|
149
|
+
}
|
|
33
150
|
}
|
|
34
151
|
}
|
|
35
152
|
}
|
|
@@ -60,6 +60,8 @@ export type AgentRuntimeConfig = {
|
|
|
60
60
|
temperature: number;
|
|
61
61
|
maxRetries: number;
|
|
62
62
|
allowToolCalls: boolean;
|
|
63
|
+
minPromptTokens: number;
|
|
64
|
+
minResponseTokens: number;
|
|
63
65
|
};
|
|
64
66
|
tools: {
|
|
65
67
|
maxToolSteps: number;
|
|
@@ -87,6 +89,13 @@ export type AgentRuntimeConfig = {
|
|
|
87
89
|
maxBytes: number;
|
|
88
90
|
httpTimeoutMs: number;
|
|
89
91
|
};
|
|
92
|
+
progress: {
|
|
93
|
+
enabled: boolean;
|
|
94
|
+
minIntervalMs: number;
|
|
95
|
+
notifyTools: string[];
|
|
96
|
+
notifyOnStart: boolean;
|
|
97
|
+
notifyOnError: boolean;
|
|
98
|
+
};
|
|
90
99
|
toolSummary: {
|
|
91
100
|
enabled: boolean;
|
|
92
101
|
maxBytes: number;
|
|
@@ -160,7 +169,7 @@ const DEFAULT_AGENT_CONFIG: AgentRuntimeConfig['agent'] = {
|
|
|
160
169
|
planner: {
|
|
161
170
|
enabled: true,
|
|
162
171
|
mode: 'auto',
|
|
163
|
-
minTokens:
|
|
172
|
+
minTokens: 800,
|
|
164
173
|
triggerRegex: '(plan|steps|roadmap|research|design|architecture|spec|strategy)',
|
|
165
174
|
maxOutputTokens: 200,
|
|
166
175
|
temperature: 0.2
|
|
@@ -170,7 +179,9 @@ const DEFAULT_AGENT_CONFIG: AgentRuntimeConfig['agent'] = {
|
|
|
170
179
|
maxOutputTokens: 120,
|
|
171
180
|
temperature: 0,
|
|
172
181
|
maxRetries: 1,
|
|
173
|
-
allowToolCalls: false
|
|
182
|
+
allowToolCalls: false,
|
|
183
|
+
minPromptTokens: 400,
|
|
184
|
+
minResponseTokens: 160
|
|
174
185
|
},
|
|
175
186
|
tools: {
|
|
176
187
|
maxToolSteps: 24,
|
|
@@ -198,6 +209,13 @@ const DEFAULT_AGENT_CONFIG: AgentRuntimeConfig['agent'] = {
|
|
|
198
209
|
maxBytes: 800_000,
|
|
199
210
|
httpTimeoutMs: 20_000
|
|
200
211
|
},
|
|
212
|
+
progress: {
|
|
213
|
+
enabled: true,
|
|
214
|
+
minIntervalMs: 30_000,
|
|
215
|
+
notifyTools: ['WebSearch', 'WebFetch', 'Bash', 'GitClone', 'NpmInstall'],
|
|
216
|
+
notifyOnStart: true,
|
|
217
|
+
notifyOnError: true
|
|
218
|
+
},
|
|
201
219
|
toolSummary: {
|
|
202
220
|
enabled: true,
|
|
203
221
|
maxBytes: 60_000,
|
|
@@ -40,6 +40,11 @@ export interface ContainerInput {
|
|
|
40
40
|
modelContextTokens?: number;
|
|
41
41
|
modelMaxOutputTokens?: number;
|
|
42
42
|
modelTemperature?: number;
|
|
43
|
+
timezone?: string;
|
|
44
|
+
disablePlanner?: boolean;
|
|
45
|
+
disableResponseValidation?: boolean;
|
|
46
|
+
responseValidationMaxRetries?: number;
|
|
47
|
+
disableMemoryExtraction?: boolean;
|
|
43
48
|
streaming?: {
|
|
44
49
|
enabled?: boolean;
|
|
45
50
|
draftId?: number;
|
|
@@ -63,6 +68,12 @@ export interface ContainerOutput {
|
|
|
63
68
|
session_recall_count?: number;
|
|
64
69
|
memory_items_upserted?: number;
|
|
65
70
|
memory_items_extracted?: number;
|
|
71
|
+
timings?: {
|
|
72
|
+
planner_ms?: number;
|
|
73
|
+
response_validation_ms?: number;
|
|
74
|
+
memory_extraction_ms?: number;
|
|
75
|
+
tool_ms?: number;
|
|
76
|
+
};
|
|
66
77
|
tool_calls?: Array<{
|
|
67
78
|
name: string;
|
|
68
79
|
args?: unknown;
|
|
@@ -318,6 +318,7 @@ function buildSystemInstructions(params: {
|
|
|
318
318
|
taskId?: string;
|
|
319
319
|
isBackgroundJob: boolean;
|
|
320
320
|
jobId?: string;
|
|
321
|
+
timezone?: string;
|
|
321
322
|
planBlock?: string;
|
|
322
323
|
taskExtractionPack?: PromptPack | null;
|
|
323
324
|
responseQualityPack?: PromptPack | null;
|
|
@@ -342,7 +343,7 @@ function buildSystemInstructions(params: {
|
|
|
342
343
|
'- `mcp__dotclaw__spawn_job`: start a background job.',
|
|
343
344
|
'- `mcp__dotclaw__job_status`, `mcp__dotclaw__list_jobs`, `mcp__dotclaw__cancel_job`.',
|
|
344
345
|
'- `mcp__dotclaw__job_update`: log job progress or notify the user.',
|
|
345
|
-
'
|
|
346
|
+
'Rule: If the task is likely to take more than ~2 minutes or needs multi-step research/coding, you MUST call `mcp__dotclaw__spawn_job` immediately and tell the user you queued it. Do not run long tasks in the foreground.',
|
|
346
347
|
'- `mcp__dotclaw__register_group`: main group only.',
|
|
347
348
|
'- `mcp__dotclaw__remove_group`, `mcp__dotclaw__list_groups`: main group only.',
|
|
348
349
|
'- `mcp__dotclaw__set_model`: main group only.',
|
|
@@ -425,6 +426,10 @@ function buildSystemInstructions(params: {
|
|
|
425
426
|
? `Behavior overrides:\n${JSON.stringify(params.behaviorConfig, null, 2)}`
|
|
426
427
|
: '';
|
|
427
428
|
|
|
429
|
+
const timezoneNote = params.timezone
|
|
430
|
+
? `Timezone: ${params.timezone}. Use this timezone when interpreting or presenting timestamps unless the user specifies another.`
|
|
431
|
+
: '';
|
|
432
|
+
|
|
428
433
|
const scheduledNote = params.isScheduledTask
|
|
429
434
|
? `You are running as a scheduled task${params.taskId ? ` (task id: ${params.taskId})` : ''}. If you need to communicate, use \`mcp__dotclaw__send_message\`.`
|
|
430
435
|
: '';
|
|
@@ -432,7 +437,7 @@ function buildSystemInstructions(params: {
|
|
|
432
437
|
? 'You are running in the background for a user request. Focus on completing the task and return a complete response without asking follow-up questions unless strictly necessary.'
|
|
433
438
|
: '';
|
|
434
439
|
const jobNote = params.isBackgroundJob
|
|
435
|
-
? `You are running as a background job${params.jobId ? ` (job id: ${params.jobId})` : ''}. Return a complete result.
|
|
440
|
+
? `You are running as a background job${params.jobId ? ` (job id: ${params.jobId})` : ''}. Return a complete result. If the task will take more than a few minutes, send periodic \`mcp__dotclaw__job_update\` messages with milestones or intermediate findings (roughly every ~5 minutes or after major steps). Prefer writing large outputs to the job artifacts directory.`
|
|
436
441
|
: '';
|
|
437
442
|
const jobArtifactsNote = params.isBackgroundJob && params.jobId
|
|
438
443
|
? `Job artifacts directory: /workspace/group/jobs/${params.jobId}`
|
|
@@ -496,6 +501,7 @@ function buildSystemInstructions(params: {
|
|
|
496
501
|
browserAutomation,
|
|
497
502
|
groupNotes,
|
|
498
503
|
globalNotes,
|
|
504
|
+
timezoneNote,
|
|
499
505
|
params.planBlock || '',
|
|
500
506
|
toolCallingBlock,
|
|
501
507
|
toolOutcomeBlock,
|
|
@@ -835,26 +841,30 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
835
841
|
const maxToolSteps = Number.isFinite(input.maxToolSteps)
|
|
836
842
|
? Math.max(1, Math.floor(input.maxToolSteps as number))
|
|
837
843
|
: agent.tools.maxToolSteps;
|
|
838
|
-
const memoryExtractionEnabled = agent.memory.extraction.enabled;
|
|
844
|
+
const memoryExtractionEnabled = agent.memory.extraction.enabled && !input.disableMemoryExtraction;
|
|
839
845
|
const isDaemon = process.env.DOTCLAW_DAEMON === '1';
|
|
840
846
|
const memoryExtractionAsync = agent.memory.extraction.async;
|
|
841
847
|
const memoryExtractionMaxMessages = agent.memory.extraction.maxMessages;
|
|
842
848
|
const memoryExtractionMaxOutputTokens = agent.memory.extraction.maxOutputTokens;
|
|
843
849
|
const memoryExtractScheduled = agent.memory.extractScheduled;
|
|
844
850
|
const memoryArchiveSync = agent.memory.archiveSync;
|
|
845
|
-
const plannerEnabled = agent.planner.enabled;
|
|
851
|
+
const plannerEnabled = agent.planner.enabled && !input.disablePlanner;
|
|
846
852
|
const plannerMode = String(agent.planner.mode || 'auto').toLowerCase();
|
|
847
853
|
const plannerMinTokens = agent.planner.minTokens;
|
|
848
854
|
const plannerTrigger = buildPlannerTrigger(agent.planner.triggerRegex);
|
|
849
855
|
const plannerModel = agent.models.planner;
|
|
850
856
|
const plannerMaxOutputTokens = agent.planner.maxOutputTokens;
|
|
851
857
|
const plannerTemperature = agent.planner.temperature;
|
|
852
|
-
const responseValidateEnabled = agent.responseValidation.enabled;
|
|
858
|
+
const responseValidateEnabled = agent.responseValidation.enabled && !input.disableResponseValidation;
|
|
853
859
|
const responseValidateModel = agent.models.responseValidation;
|
|
854
860
|
const responseValidateMaxOutputTokens = agent.responseValidation.maxOutputTokens;
|
|
855
861
|
const responseValidateTemperature = agent.responseValidation.temperature;
|
|
856
|
-
const responseValidateMaxRetries =
|
|
862
|
+
const responseValidateMaxRetries = Number.isFinite(input.responseValidationMaxRetries)
|
|
863
|
+
? Math.max(0, Math.floor(input.responseValidationMaxRetries as number))
|
|
864
|
+
: agent.responseValidation.maxRetries;
|
|
857
865
|
const responseValidateAllowToolCalls = agent.responseValidation.allowToolCalls;
|
|
866
|
+
const responseValidateMinPromptTokens = agent.responseValidation.minPromptTokens || 0;
|
|
867
|
+
const responseValidateMinResponseTokens = agent.responseValidation.minResponseTokens || 0;
|
|
858
868
|
const maxContextMessageTokens = agent.context.maxContextMessageTokens;
|
|
859
869
|
const streamingEnabled = Boolean(input.streaming?.enabled && typeof input.streaming?.draftId === 'number');
|
|
860
870
|
const streamingDraftId = streamingEnabled ? input.streaming?.draftId : undefined;
|
|
@@ -884,6 +894,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
884
894
|
const toolCalls: ToolCallRecord[] = [];
|
|
885
895
|
let memoryItemsUpserted = 0;
|
|
886
896
|
let memoryItemsExtracted = 0;
|
|
897
|
+
const timings: { planner_ms?: number; response_validation_ms?: number; memory_extraction_ms?: number; tool_ms?: number } = {};
|
|
887
898
|
const ipc = createIpcHandlers({
|
|
888
899
|
chatJid: input.chatJid,
|
|
889
900
|
groupFolder: input.groupFolder,
|
|
@@ -897,7 +908,11 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
897
908
|
onToolCall: (call) => {
|
|
898
909
|
toolCalls.push(call);
|
|
899
910
|
},
|
|
900
|
-
policy: input.toolPolicy
|
|
911
|
+
policy: input.toolPolicy,
|
|
912
|
+
jobProgress: {
|
|
913
|
+
jobId: input.jobId,
|
|
914
|
+
enabled: Boolean(input.isBackgroundJob)
|
|
915
|
+
}
|
|
901
916
|
});
|
|
902
917
|
|
|
903
918
|
let streamLastSentAt = 0;
|
|
@@ -1083,6 +1098,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1083
1098
|
taskId: input.taskId,
|
|
1084
1099
|
isBackgroundJob: !!input.isBackgroundJob,
|
|
1085
1100
|
jobId: input.jobId,
|
|
1101
|
+
timezone: typeof input.timezone === 'string' ? input.timezone : undefined,
|
|
1086
1102
|
planBlock: planBlockValue,
|
|
1087
1103
|
taskExtractionPack: taskPackResult?.pack || null,
|
|
1088
1104
|
responseQualityPack: responseQualityResult?.pack || null,
|
|
@@ -1109,6 +1125,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1109
1125
|
trigger: plannerTrigger
|
|
1110
1126
|
})) {
|
|
1111
1127
|
try {
|
|
1128
|
+
const plannerStartedAt = Date.now();
|
|
1112
1129
|
const plannerPrompt = buildPlannerPrompt(plannerContextMessages);
|
|
1113
1130
|
const plannerResult = await openrouter.callModel({
|
|
1114
1131
|
model: plannerModel,
|
|
@@ -1122,6 +1139,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1122
1139
|
if (plan) {
|
|
1123
1140
|
planBlock = formatPlanBlock(plan);
|
|
1124
1141
|
}
|
|
1142
|
+
timings.planner_ms = Date.now() - plannerStartedAt;
|
|
1125
1143
|
} catch (err) {
|
|
1126
1144
|
log(`Planner failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1127
1145
|
}
|
|
@@ -1245,6 +1263,8 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1245
1263
|
modelToolCalls = firstAttempt.modelToolCalls;
|
|
1246
1264
|
|
|
1247
1265
|
const shouldValidate = responseValidateEnabled
|
|
1266
|
+
&& promptTokens >= responseValidateMinPromptTokens
|
|
1267
|
+
&& completionTokens >= responseValidateMinResponseTokens
|
|
1248
1268
|
&& (responseValidateAllowToolCalls || modelToolCalls.length === 0);
|
|
1249
1269
|
if (shouldValidate) {
|
|
1250
1270
|
let retriesLeft = responseValidateMaxRetries;
|
|
@@ -1257,6 +1277,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1257
1277
|
validationResult = { verdict: 'fail', issues: ['Response was empty.'], missing: [] };
|
|
1258
1278
|
} else {
|
|
1259
1279
|
try {
|
|
1280
|
+
const validationStartedAt = Date.now();
|
|
1260
1281
|
validationResult = await validateResponseQuality({
|
|
1261
1282
|
openrouter,
|
|
1262
1283
|
model: responseValidateModel,
|
|
@@ -1265,6 +1286,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1265
1286
|
maxOutputTokens: responseValidateMaxOutputTokens,
|
|
1266
1287
|
temperature: responseValidateTemperature
|
|
1267
1288
|
});
|
|
1289
|
+
timings.response_validation_ms = (timings.response_validation_ms ?? 0) + (Date.now() - validationStartedAt);
|
|
1268
1290
|
} catch (err) {
|
|
1269
1291
|
log(`Response validation failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1270
1292
|
}
|
|
@@ -1306,6 +1328,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1306
1328
|
session_recall_count: sessionRecallCount,
|
|
1307
1329
|
memory_items_upserted: memoryItemsUpserted,
|
|
1308
1330
|
memory_items_extracted: memoryItemsExtracted,
|
|
1331
|
+
timings: Object.keys(timings).length > 0 ? timings : undefined,
|
|
1309
1332
|
tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
1310
1333
|
latency_ms: latencyMs
|
|
1311
1334
|
};
|
|
@@ -1335,6 +1358,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1335
1358
|
const runMemoryExtraction = async () => {
|
|
1336
1359
|
const extractionMessages = history.slice(-memoryExtractionMaxMessages);
|
|
1337
1360
|
if (extractionMessages.length === 0) return;
|
|
1361
|
+
const extractionStartedAt = Date.now();
|
|
1338
1362
|
const extractionPrompt = buildMemoryExtractionPrompt({
|
|
1339
1363
|
assistantName,
|
|
1340
1364
|
userId: input.userId,
|
|
@@ -1380,6 +1404,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1380
1404
|
memoryItemsExtracted += normalizedItems.length;
|
|
1381
1405
|
memoryItemsUpserted += normalizedItems.length;
|
|
1382
1406
|
}
|
|
1407
|
+
timings.memory_extraction_ms = (timings.memory_extraction_ms ?? 0) + (Date.now() - extractionStartedAt);
|
|
1383
1408
|
};
|
|
1384
1409
|
|
|
1385
1410
|
if (memoryExtractionEnabled && (!input.isScheduledTask || memoryExtractScheduled)) {
|
|
@@ -1398,6 +1423,12 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1398
1423
|
|
|
1399
1424
|
// Normalize empty/whitespace-only responses to null
|
|
1400
1425
|
const finalResult = responseText && responseText.trim() ? responseText : null;
|
|
1426
|
+
if (toolCalls.length > 0) {
|
|
1427
|
+
const totalToolMs = toolCalls.reduce((sum, call) => sum + (call.duration_ms || 0), 0);
|
|
1428
|
+
if (totalToolMs > 0) {
|
|
1429
|
+
timings.tool_ms = totalToolMs;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1401
1432
|
|
|
1402
1433
|
return {
|
|
1403
1434
|
status: 'success',
|
|
@@ -1413,6 +1444,7 @@ export async function runAgentOnce(input: ContainerInput): Promise<ContainerOutp
|
|
|
1413
1444
|
session_recall_count: sessionRecallCount,
|
|
1414
1445
|
memory_items_upserted: memoryItemsUpserted,
|
|
1415
1446
|
memory_items_extracted: memoryItemsExtracted,
|
|
1447
|
+
timings: Object.keys(timings).length > 0 ? timings : undefined,
|
|
1416
1448
|
tool_calls: toolCalls.length > 0 ? toolCalls : undefined,
|
|
1417
1449
|
latency_ms: latencyMs
|
|
1418
1450
|
};
|
|
@@ -39,6 +39,13 @@ type ToolRuntime = {
|
|
|
39
39
|
tools: string[];
|
|
40
40
|
timeoutMs: number;
|
|
41
41
|
};
|
|
42
|
+
progress: {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
minIntervalMs: number;
|
|
45
|
+
notifyTools: string[];
|
|
46
|
+
notifyOnStart: boolean;
|
|
47
|
+
notifyOnError: boolean;
|
|
48
|
+
};
|
|
42
49
|
openrouter: {
|
|
43
50
|
siteUrl: string;
|
|
44
51
|
siteName: string;
|
|
@@ -86,6 +93,13 @@ function buildToolRuntime(config: AgentRuntimeConfig['agent']): ToolRuntime {
|
|
|
86
93
|
tools: toolSummaryTools,
|
|
87
94
|
timeoutMs: toolSummaryTimeoutMs
|
|
88
95
|
},
|
|
96
|
+
progress: {
|
|
97
|
+
enabled: config.tools.progress.enabled,
|
|
98
|
+
minIntervalMs: config.tools.progress.minIntervalMs,
|
|
99
|
+
notifyTools: config.tools.progress.notifyTools,
|
|
100
|
+
notifyOnStart: config.tools.progress.notifyOnStart,
|
|
101
|
+
notifyOnError: config.tools.progress.notifyOnError
|
|
102
|
+
},
|
|
89
103
|
openrouter: {
|
|
90
104
|
siteUrl: config.openrouter.siteUrl,
|
|
91
105
|
siteName: config.openrouter.siteName
|
|
@@ -824,12 +838,23 @@ async function maybeSummarizeToolResult<T>(name: string, result: T, runtime: Too
|
|
|
824
838
|
return payload.apply(limited.text) as T;
|
|
825
839
|
}
|
|
826
840
|
|
|
827
|
-
export function createTools(
|
|
841
|
+
export function createTools(
|
|
842
|
+
ctx: IpcContext,
|
|
843
|
+
config: AgentRuntimeConfig['agent'],
|
|
844
|
+
options?: { onToolCall?: ToolCallLogger; policy?: ToolPolicy; jobProgress?: { jobId?: string; enabled?: boolean } }
|
|
845
|
+
) {
|
|
828
846
|
const runtime = buildToolRuntime(config);
|
|
829
847
|
const ipc = createIpcHandlers(ctx, config.ipc);
|
|
830
848
|
const isMain = ctx.isMain;
|
|
831
849
|
const onToolCall = options?.onToolCall;
|
|
832
850
|
const policy = options?.policy;
|
|
851
|
+
const progressConfig = runtime.progress;
|
|
852
|
+
const progressJobId = options?.jobProgress?.jobId;
|
|
853
|
+
const progressEnabled = Boolean(progressJobId && progressConfig.enabled && options?.jobProgress?.enabled !== false);
|
|
854
|
+
const progressNotifyTools = new Set(
|
|
855
|
+
(progressConfig.notifyTools || []).map(item => item.trim().toLowerCase()).filter(Boolean)
|
|
856
|
+
);
|
|
857
|
+
let lastProgressNotifyAt = 0;
|
|
833
858
|
const allowList = (policy?.allow || []).map(item => item.toLowerCase());
|
|
834
859
|
const denyList = (policy?.deny || []).map(item => item.toLowerCase());
|
|
835
860
|
const maxPerRunConfig = policy?.max_per_run || {};
|
|
@@ -849,24 +874,62 @@ export function createTools(ctx: IpcContext, config: AgentRuntimeConfig['agent']
|
|
|
849
874
|
const webFetchAllowlist = runtime.webfetchAllowlist;
|
|
850
875
|
const webFetchBlocklist = runtime.webfetchBlocklist;
|
|
851
876
|
|
|
877
|
+
const shouldNotifyTool = (name: string) => {
|
|
878
|
+
if (!progressEnabled) return false;
|
|
879
|
+
if (!progressNotifyTools || progressNotifyTools.size === 0) return false;
|
|
880
|
+
return progressNotifyTools.has(name.toLowerCase());
|
|
881
|
+
};
|
|
882
|
+
|
|
883
|
+
const sendJobUpdate = (payload: { message: string; level?: 'info' | 'progress' | 'warn' | 'error'; notify?: boolean; data?: Record<string, unknown> }) => {
|
|
884
|
+
if (!progressEnabled || !progressJobId) return;
|
|
885
|
+
void ipc.jobUpdate({
|
|
886
|
+
job_id: progressJobId,
|
|
887
|
+
message: payload.message,
|
|
888
|
+
level: payload.level,
|
|
889
|
+
notify: payload.notify,
|
|
890
|
+
data: payload.data
|
|
891
|
+
}).catch(() => undefined);
|
|
892
|
+
};
|
|
893
|
+
|
|
852
894
|
const wrapExecute = <TInput, TOutput>(name: string, execute: (args: TInput) => Promise<TOutput>) => {
|
|
853
895
|
return async (args: TInput): Promise<TOutput> => {
|
|
854
896
|
const start = Date.now();
|
|
897
|
+
const normalizedName = name.toLowerCase();
|
|
898
|
+
const isSystemTool = normalizedName.startsWith('mcp__');
|
|
855
899
|
try {
|
|
856
|
-
|
|
857
|
-
if (denyList.includes(normalized)) {
|
|
900
|
+
if (denyList.includes(normalizedName)) {
|
|
858
901
|
throw new Error(`Tool is disabled by policy: ${name}`);
|
|
859
902
|
}
|
|
860
|
-
if (allowList.length > 0 && !allowList.includes(
|
|
903
|
+
if (allowList.length > 0 && !allowList.includes(normalizedName)) {
|
|
861
904
|
throw new Error(`Tool not allowed by policy: ${name}`);
|
|
862
905
|
}
|
|
863
906
|
const currentCount = usageCounts.get(name) || 0;
|
|
864
|
-
const maxAllowed = maxPerRun.get(
|
|
907
|
+
const maxAllowed = maxPerRun.get(normalizedName) ?? defaultMax;
|
|
865
908
|
if (Number.isFinite(maxAllowed) && maxAllowed > 0 && currentCount >= maxAllowed) {
|
|
866
909
|
throw new Error(`Tool usage limit reached for ${name} (max ${maxAllowed} per run)`);
|
|
867
910
|
}
|
|
868
911
|
usageCounts.set(name, currentCount + 1);
|
|
869
912
|
|
|
913
|
+
if (!isSystemTool && shouldNotifyTool(name) && progressConfig.notifyOnStart) {
|
|
914
|
+
const now = Date.now();
|
|
915
|
+
if (now - lastProgressNotifyAt >= progressConfig.minIntervalMs) {
|
|
916
|
+
lastProgressNotifyAt = now;
|
|
917
|
+
sendJobUpdate({
|
|
918
|
+
message: `Running ${name}...`,
|
|
919
|
+
level: 'progress',
|
|
920
|
+
notify: true,
|
|
921
|
+
data: { tool: name, stage: 'start' }
|
|
922
|
+
});
|
|
923
|
+
} else {
|
|
924
|
+
sendJobUpdate({
|
|
925
|
+
message: `Running ${name}...`,
|
|
926
|
+
level: 'progress',
|
|
927
|
+
notify: false,
|
|
928
|
+
data: { tool: name, stage: 'start' }
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
870
933
|
const rawResult = await execute(args);
|
|
871
934
|
const result = await maybeSummarizeToolResult(name, rawResult, runtime);
|
|
872
935
|
let outputBytes: number | undefined;
|
|
@@ -888,6 +951,14 @@ export function createTools(ctx: IpcContext, config: AgentRuntimeConfig['agent']
|
|
|
888
951
|
output_bytes: outputBytes,
|
|
889
952
|
output_truncated: outputTruncated
|
|
890
953
|
});
|
|
954
|
+
if (!isSystemTool && shouldNotifyTool(name)) {
|
|
955
|
+
sendJobUpdate({
|
|
956
|
+
message: `${name} finished.`,
|
|
957
|
+
level: 'info',
|
|
958
|
+
notify: false,
|
|
959
|
+
data: { tool: name, stage: 'end', ok: true, duration_ms: Date.now() - start }
|
|
960
|
+
});
|
|
961
|
+
}
|
|
891
962
|
return result;
|
|
892
963
|
} catch (err) {
|
|
893
964
|
onToolCall?.({
|
|
@@ -897,6 +968,14 @@ export function createTools(ctx: IpcContext, config: AgentRuntimeConfig['agent']
|
|
|
897
968
|
duration_ms: Date.now() - start,
|
|
898
969
|
error: err instanceof Error ? err.message : String(err)
|
|
899
970
|
});
|
|
971
|
+
if (!isSystemTool && shouldNotifyTool(name) && progressConfig.notifyOnError) {
|
|
972
|
+
sendJobUpdate({
|
|
973
|
+
message: `${name} failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
974
|
+
level: 'error',
|
|
975
|
+
notify: true,
|
|
976
|
+
data: { tool: name, stage: 'end', ok: false, duration_ms: Date.now() - start }
|
|
977
|
+
});
|
|
978
|
+
}
|
|
900
979
|
throw err;
|
|
901
980
|
}
|
|
902
981
|
};
|
package/dist/agent-context.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ export type AgentContext = {
|
|
|
30
30
|
tokenEstimate: ReturnType<typeof getTokenEstimateConfig>;
|
|
31
31
|
modelCapabilities: ModelCapabilities;
|
|
32
32
|
dynamicMemoryBudget: number;
|
|
33
|
+
timings: {
|
|
34
|
+
context_build_ms?: number;
|
|
35
|
+
memory_recall_ms?: number;
|
|
36
|
+
};
|
|
33
37
|
};
|
|
34
38
|
export declare function buildAgentContext(params: {
|
|
35
39
|
groupFolder: string;
|
|
@@ -39,5 +43,6 @@ export declare function buildAgentContext(params: {
|
|
|
39
43
|
recallMaxTokens: number;
|
|
40
44
|
toolAllow?: string[];
|
|
41
45
|
toolDeny?: string[];
|
|
46
|
+
recallEnabled?: boolean;
|
|
42
47
|
}): Promise<AgentContext>;
|
|
43
48
|
//# sourceMappingURL=agent-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-context.d.ts","sourceRoot":"","sources":["../src/agent-context.ts"],"names":[],"mappings":"AAGA,OAAO,EAA+C,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG3F,OAAO,EAAgB,iBAAiB,EAAE,sBAAsB,EAAE,eAAe,EAAwB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxJ,MAAM,MAAM,YAAY,GAAG;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAC9G,aAAa,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE;YAAE,cAAc,CAAC,EAAE,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC3H,aAAa,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IACpD,YAAY,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;IACjD,aAAa,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IACzD,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,mBAAmB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-context.d.ts","sourceRoot":"","sources":["../src/agent-context.ts"],"names":[],"mappings":"AAGA,OAAO,EAA+C,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG3F,OAAO,EAAgB,iBAAiB,EAAE,sBAAsB,EAAE,eAAe,EAAwB,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxJ,MAAM,MAAM,YAAY,GAAG;IACzB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5E,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAC9G,aAAa,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE;YAAE,cAAc,CAAC,EAAE,MAAM,CAAC;YAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;IAC3H,aAAa,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IACpD,YAAY,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;IACjD,aAAa,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IACzD,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,OAAO,EAAE;QACP,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;CACH,CAAC;AA4BF,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,YAAY,CAAC,CAmGxB"}
|
package/dist/agent-context.js
CHANGED
|
@@ -22,6 +22,7 @@ function calculateMemoryBudget(modelCapabilities, maxOutputTokens, configuredMax
|
|
|
22
22
|
return Math.min(Math.max(800, Math.min(4000, calculatedBudget)), configuredMax);
|
|
23
23
|
}
|
|
24
24
|
export async function buildAgentContext(params) {
|
|
25
|
+
const startedAt = Date.now();
|
|
25
26
|
const runtime = loadRuntimeConfig();
|
|
26
27
|
const defaultModel = runtime.host.defaultModel;
|
|
27
28
|
const modelRegistry = loadModelRegistry(defaultModel);
|
|
@@ -36,13 +37,19 @@ export async function buildAgentContext(params) {
|
|
|
36
37
|
const modelCapabilities = await getModelCapabilities(resolvedModel.model);
|
|
37
38
|
// Calculate dynamic memory budget based on model context window
|
|
38
39
|
const dynamicMemoryBudget = calculateMemoryBudget(modelCapabilities, runtime.agent.context.maxOutputTokens, params.recallMaxTokens);
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
let memoryRecall = [];
|
|
41
|
+
let memoryRecallMs;
|
|
42
|
+
if (params.recallEnabled !== false && params.recallMaxResults > 0 && params.recallMaxTokens > 0) {
|
|
43
|
+
const recallStart = Date.now();
|
|
44
|
+
memoryRecall = await buildHybridMemoryRecall({
|
|
45
|
+
groupFolder: params.groupFolder,
|
|
46
|
+
userId: params.userId ?? null,
|
|
47
|
+
query: params.recallQuery,
|
|
48
|
+
maxResults: params.recallMaxResults,
|
|
49
|
+
maxTokens: dynamicMemoryBudget
|
|
50
|
+
});
|
|
51
|
+
memoryRecallMs = Date.now() - recallStart;
|
|
52
|
+
}
|
|
46
53
|
const userProfile = buildUserProfile({
|
|
47
54
|
groupFolder: params.groupFolder,
|
|
48
55
|
userId: params.userId ?? null
|
|
@@ -93,7 +100,11 @@ export async function buildAgentContext(params) {
|
|
|
93
100
|
modelPricing,
|
|
94
101
|
tokenEstimate,
|
|
95
102
|
modelCapabilities,
|
|
96
|
-
dynamicMemoryBudget
|
|
103
|
+
dynamicMemoryBudget,
|
|
104
|
+
timings: {
|
|
105
|
+
context_build_ms: Date.now() - startedAt,
|
|
106
|
+
memory_recall_ms: memoryRecallMs
|
|
107
|
+
}
|
|
97
108
|
};
|
|
98
109
|
}
|
|
99
110
|
//# sourceMappingURL=agent-context.js.map
|