@vantageos/agent-engine 0.1.0-alpha.5 → 0.1.0-alpha.6
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 +229 -40
- package/dist/component/_generated/api.d.ts +31 -0
- package/dist/component/_generated/component.d.ts +346 -2
- package/dist/component/convex.config.js +19 -0
- package/dist/component/engine/agents.d.ts +10 -0
- package/dist/component/engine/agents.js +21 -0
- package/dist/component/engine/awaitEventTimeout.d.ts +13 -0
- package/dist/component/engine/awaitEventTimeout.js +82 -0
- package/dist/component/engine/delegation.d.ts +75 -0
- package/dist/component/engine/delegation.js +329 -0
- package/dist/component/engine/directory.d.ts +9 -0
- package/dist/component/engine/directory.js +45 -0
- package/dist/component/engine/habits.d.ts +70 -0
- package/dist/component/engine/habits.js +219 -0
- package/dist/component/engine/mandates.d.ts +74 -0
- package/dist/component/engine/mandates.js +272 -0
- package/dist/component/engine/sandboxCallback.d.ts +36 -0
- package/dist/component/engine/sandboxCallback.js +262 -0
- package/dist/component/engine/sessions.d.ts +6 -2
- package/dist/component/engine/sessions.js +42 -5
- package/dist/component/engine/vpConnection.d.ts +69 -0
- package/dist/component/engine/vpConnection.js +221 -0
- package/dist/component/engine/wakeup.d.ts +33 -0
- package/dist/component/engine/wakeup.js +230 -0
- package/dist/component/engine/workflows.d.ts +11 -0
- package/dist/component/engine/workflows.js +87 -0
- package/dist/component/schema.d.ts +365 -4
- package/dist/component/schema.js +353 -1
- package/dist/component/testFixtures/delegationDemoWorkflow.d.ts +18 -0
- package/dist/component/testFixtures/delegationDemoWorkflow.js +76 -0
- package/dist/component/testFixtures/sandboxDemoWorkflow.d.ts +19 -0
- package/dist/component/testFixtures/sandboxDemoWorkflow.js +69 -0
- package/dist/component/testFixtures/vpTool.d.ts +4 -0
- package/dist/component/testFixtures/vpTool.js +25 -0
- package/dist/component/testFixtures/wakeupDemoWorkflow.d.ts +19 -0
- package/dist/component/testFixtures/wakeupDemoWorkflow.js +77 -0
- package/dist/component/testFixtures/wakeupWork.d.ts +8 -0
- package/dist/component/testFixtures/wakeupWork.js +21 -0
- package/package.json +2 -1
|
@@ -23,10 +23,15 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
23
23
|
agents: {
|
|
24
24
|
create: FunctionReference<"mutation", "internal", {
|
|
25
25
|
createdBy: string;
|
|
26
|
+
description?: string;
|
|
26
27
|
instructions: string;
|
|
28
|
+
maxInputTokensPerSession?: number | false;
|
|
29
|
+
maxSubagents?: number;
|
|
27
30
|
model: string;
|
|
31
|
+
modelProvider?: "gateway" | "openrouter";
|
|
28
32
|
name: string;
|
|
29
33
|
orgId: string;
|
|
34
|
+
reasoningEffort?: "none" | "low" | "medium" | "high";
|
|
30
35
|
}, string, Name>;
|
|
31
36
|
get: FunctionReference<"query", "internal", {
|
|
32
37
|
agentId: string;
|
|
@@ -36,14 +41,88 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
36
41
|
_id: string;
|
|
37
42
|
createdAt: number;
|
|
38
43
|
createdBy: string;
|
|
44
|
+
description?: string;
|
|
39
45
|
instructions: string;
|
|
46
|
+
maxInputTokensPerSession?: number | false;
|
|
47
|
+
maxSubagents?: number;
|
|
40
48
|
model: string;
|
|
49
|
+
modelProvider?: "gateway" | "openrouter";
|
|
41
50
|
name: string;
|
|
42
51
|
orgId: string;
|
|
52
|
+
reasoningEffort?: "none" | "low" | "medium" | "high";
|
|
43
53
|
status: "draft" | "live" | "archived";
|
|
44
54
|
updatedAt: number;
|
|
45
55
|
} | null, Name>;
|
|
46
56
|
};
|
|
57
|
+
awaitEventTimeout: {
|
|
58
|
+
cancel: FunctionReference<"mutation", "internal", {
|
|
59
|
+
orgId: string;
|
|
60
|
+
timeoutRowId: string;
|
|
61
|
+
}, null, Name>;
|
|
62
|
+
schedule: FunctionReference<"mutation", "internal", {
|
|
63
|
+
awaitedEventName: string;
|
|
64
|
+
orgId: string;
|
|
65
|
+
sessionId: string;
|
|
66
|
+
timeoutMs: number;
|
|
67
|
+
}, string, Name>;
|
|
68
|
+
};
|
|
69
|
+
delegation: {
|
|
70
|
+
declareSubagent: FunctionReference<"mutation", "internal", {
|
|
71
|
+
childAgentId: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
orgId: string;
|
|
74
|
+
parentAgentId: string;
|
|
75
|
+
toolName: string;
|
|
76
|
+
}, string, Name>;
|
|
77
|
+
delegateToSubagent: FunctionReference<"action", "internal", {
|
|
78
|
+
awaitedEventName: string;
|
|
79
|
+
cost: number;
|
|
80
|
+
orgId: string;
|
|
81
|
+
payload?: string;
|
|
82
|
+
reason: string;
|
|
83
|
+
scope: string;
|
|
84
|
+
subagentId: string;
|
|
85
|
+
workFunctionHandle: string;
|
|
86
|
+
workflowId: string;
|
|
87
|
+
}, string, Name>;
|
|
88
|
+
invokeAgentClone: FunctionReference<"action", "internal", {
|
|
89
|
+
agentId: string;
|
|
90
|
+
awaitedEventName: string;
|
|
91
|
+
cost: number;
|
|
92
|
+
orgId: string;
|
|
93
|
+
payload?: string;
|
|
94
|
+
reason: string;
|
|
95
|
+
scope: string;
|
|
96
|
+
viaAgentTool: boolean;
|
|
97
|
+
workFunctionHandle: string;
|
|
98
|
+
workflowId: string;
|
|
99
|
+
}, string, Name>;
|
|
100
|
+
listSubagents: FunctionReference<"query", "internal", {
|
|
101
|
+
orgId: string;
|
|
102
|
+
parentAgentId: string;
|
|
103
|
+
}, Array<{
|
|
104
|
+
_creationTime: number;
|
|
105
|
+
_id: string;
|
|
106
|
+
childAgentId: string;
|
|
107
|
+
createdAt: number;
|
|
108
|
+
description?: string;
|
|
109
|
+
enabled: boolean;
|
|
110
|
+
orgId: string;
|
|
111
|
+
parentAgentId: string;
|
|
112
|
+
toolName: string;
|
|
113
|
+
}>, Name>;
|
|
114
|
+
};
|
|
115
|
+
directory: {
|
|
116
|
+
listByOrg: FunctionReference<"query", "internal", {
|
|
117
|
+
orgId: string;
|
|
118
|
+
}, Array<{
|
|
119
|
+
_id: string;
|
|
120
|
+
createdAt: number;
|
|
121
|
+
model: string;
|
|
122
|
+
name: string;
|
|
123
|
+
status: "draft" | "live" | "archived";
|
|
124
|
+
}>, Name>;
|
|
125
|
+
};
|
|
47
126
|
durableJob: {
|
|
48
127
|
cancel: FunctionReference<"mutation", "internal", {
|
|
49
128
|
jobId: string;
|
|
@@ -67,6 +146,140 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
67
146
|
totalSteps: number;
|
|
68
147
|
}, string, Name>;
|
|
69
148
|
};
|
|
149
|
+
habits: {
|
|
150
|
+
create: FunctionReference<"mutation", "internal", {
|
|
151
|
+
agentId: string;
|
|
152
|
+
cronExpression: string;
|
|
153
|
+
name: string;
|
|
154
|
+
orgId: string;
|
|
155
|
+
prompt: string;
|
|
156
|
+
}, string, Name>;
|
|
157
|
+
disable: FunctionReference<"mutation", "internal", {
|
|
158
|
+
habitId: string;
|
|
159
|
+
orgId: string;
|
|
160
|
+
}, null, Name>;
|
|
161
|
+
enable: FunctionReference<"mutation", "internal", {
|
|
162
|
+
habitId: string;
|
|
163
|
+
orgId: string;
|
|
164
|
+
}, null, Name>;
|
|
165
|
+
get: FunctionReference<"query", "internal", {
|
|
166
|
+
habitId: string;
|
|
167
|
+
orgId: string;
|
|
168
|
+
}, {
|
|
169
|
+
_creationTime: number;
|
|
170
|
+
_id: string;
|
|
171
|
+
agentId: string;
|
|
172
|
+
createdAt: number;
|
|
173
|
+
cronExpression: string;
|
|
174
|
+
cronJobId?: string;
|
|
175
|
+
enabled: boolean;
|
|
176
|
+
lastRunAt?: number;
|
|
177
|
+
name: string;
|
|
178
|
+
orgId: string;
|
|
179
|
+
prompt: string;
|
|
180
|
+
updatedAt: number;
|
|
181
|
+
} | null, Name>;
|
|
182
|
+
listForAgent: FunctionReference<"query", "internal", {
|
|
183
|
+
agentId: string;
|
|
184
|
+
orgId: string;
|
|
185
|
+
}, Array<{
|
|
186
|
+
_creationTime: number;
|
|
187
|
+
_id: string;
|
|
188
|
+
agentId: string;
|
|
189
|
+
createdAt: number;
|
|
190
|
+
cronExpression: string;
|
|
191
|
+
cronJobId?: string;
|
|
192
|
+
enabled: boolean;
|
|
193
|
+
lastRunAt?: number;
|
|
194
|
+
name: string;
|
|
195
|
+
orgId: string;
|
|
196
|
+
prompt: string;
|
|
197
|
+
updatedAt: number;
|
|
198
|
+
}>, Name>;
|
|
199
|
+
listRuns: FunctionReference<"query", "internal", {
|
|
200
|
+
habitId: string;
|
|
201
|
+
orgId: string;
|
|
202
|
+
}, Array<{
|
|
203
|
+
_creationTime: number;
|
|
204
|
+
_id: string;
|
|
205
|
+
agentId: string;
|
|
206
|
+
habitId: string;
|
|
207
|
+
orgId: string;
|
|
208
|
+
ranAt: number;
|
|
209
|
+
}>, Name>;
|
|
210
|
+
updateSchedule: FunctionReference<"mutation", "internal", {
|
|
211
|
+
cronExpression?: string;
|
|
212
|
+
habitId: string;
|
|
213
|
+
name?: string;
|
|
214
|
+
orgId: string;
|
|
215
|
+
prompt?: string;
|
|
216
|
+
}, null, Name>;
|
|
217
|
+
};
|
|
218
|
+
mandates: {
|
|
219
|
+
get: FunctionReference<"query", "internal", {
|
|
220
|
+
agentId: string;
|
|
221
|
+
orgId: string;
|
|
222
|
+
scope: string;
|
|
223
|
+
}, {
|
|
224
|
+
_creationTime: number;
|
|
225
|
+
_id: string;
|
|
226
|
+
agentId: string;
|
|
227
|
+
capacity?: number;
|
|
228
|
+
createdAt: number;
|
|
229
|
+
kind: "token bucket" | "fixed window";
|
|
230
|
+
orgId: string;
|
|
231
|
+
period: number;
|
|
232
|
+
rate: number;
|
|
233
|
+
scope: string;
|
|
234
|
+
updatedAt: number;
|
|
235
|
+
} | null, Name>;
|
|
236
|
+
listApprovals: FunctionReference<"query", "internal", {
|
|
237
|
+
agentId?: string;
|
|
238
|
+
orgId: string;
|
|
239
|
+
}, Array<{
|
|
240
|
+
_creationTime: number;
|
|
241
|
+
_id: string;
|
|
242
|
+
agentId: string;
|
|
243
|
+
createdAt: number;
|
|
244
|
+
orgId: string;
|
|
245
|
+
reason: string;
|
|
246
|
+
requestedCost: number;
|
|
247
|
+
resolvedAt?: number;
|
|
248
|
+
resolvedBy?: string;
|
|
249
|
+
scope: string;
|
|
250
|
+
status: "pending" | "approved" | "denied";
|
|
251
|
+
}>, Name>;
|
|
252
|
+
resolveApproval: FunctionReference<"mutation", "internal", {
|
|
253
|
+
approvalId: string;
|
|
254
|
+
decision: "approved" | "denied";
|
|
255
|
+
orgId: string;
|
|
256
|
+
resolvedBy: string;
|
|
257
|
+
}, null, Name>;
|
|
258
|
+
set: FunctionReference<"mutation", "internal", {
|
|
259
|
+
agentId: string;
|
|
260
|
+
capacity?: number;
|
|
261
|
+
kind: "token bucket" | "fixed window";
|
|
262
|
+
orgId: string;
|
|
263
|
+
period: number;
|
|
264
|
+
rate: number;
|
|
265
|
+
scope: string;
|
|
266
|
+
}, string, Name>;
|
|
267
|
+
spend: FunctionReference<"mutation", "internal", {
|
|
268
|
+
agentId: string;
|
|
269
|
+
cost: number;
|
|
270
|
+
orgId: string;
|
|
271
|
+
reason: string;
|
|
272
|
+
scope: string;
|
|
273
|
+
}, {
|
|
274
|
+
approvalId?: string;
|
|
275
|
+
ok: boolean;
|
|
276
|
+
}, Name>;
|
|
277
|
+
usageCount: FunctionReference<"query", "internal", {
|
|
278
|
+
agentId: string;
|
|
279
|
+
orgId: string;
|
|
280
|
+
scope: string;
|
|
281
|
+
}, number, Name>;
|
|
282
|
+
};
|
|
70
283
|
resolvers: {
|
|
71
284
|
resolveManifest: FunctionReference<"query", "internal", {
|
|
72
285
|
orgId: string;
|
|
@@ -82,6 +295,41 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
82
295
|
}>;
|
|
83
296
|
}, Name>;
|
|
84
297
|
};
|
|
298
|
+
sandboxCallback: {
|
|
299
|
+
attachSandboxId: FunctionReference<"mutation", "internal", {
|
|
300
|
+
orgId: string;
|
|
301
|
+
sandboxId: string;
|
|
302
|
+
sandboxRunId: string;
|
|
303
|
+
}, null, Name>;
|
|
304
|
+
deadLetterMalformed: FunctionReference<"mutation", "internal", {
|
|
305
|
+
deliveryId: string;
|
|
306
|
+
orgId?: string;
|
|
307
|
+
rawBody: string;
|
|
308
|
+
reason: string;
|
|
309
|
+
}, null, Name>;
|
|
310
|
+
getStatus: FunctionReference<"query", "internal", {
|
|
311
|
+
orgId: string;
|
|
312
|
+
sandboxRunId: string;
|
|
313
|
+
}, {
|
|
314
|
+
resultSummary?: string;
|
|
315
|
+
status: "pending" | "completed" | "failed" | "timedOut";
|
|
316
|
+
}, Name>;
|
|
317
|
+
processCallback: FunctionReference<"mutation", "internal", {
|
|
318
|
+
deliveryId: string;
|
|
319
|
+
orgId: string;
|
|
320
|
+
resultSummary?: string;
|
|
321
|
+
sandboxRunId: string;
|
|
322
|
+
status: "completed" | "failed";
|
|
323
|
+
}, {
|
|
324
|
+
outcome: "woke" | "duplicate" | "dead-lettered";
|
|
325
|
+
}, Name>;
|
|
326
|
+
startRun: FunctionReference<"mutation", "internal", {
|
|
327
|
+
awaitedEventName: string;
|
|
328
|
+
orgId: string;
|
|
329
|
+
timeoutMs: number;
|
|
330
|
+
workflowId: string;
|
|
331
|
+
}, string, Name>;
|
|
332
|
+
};
|
|
85
333
|
sessions: {
|
|
86
334
|
appendReasoning: FunctionReference<"mutation", "internal", {
|
|
87
335
|
chunk: string;
|
|
@@ -105,7 +353,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
105
353
|
_creationTime: number;
|
|
106
354
|
_id: string;
|
|
107
355
|
createdAt: number;
|
|
108
|
-
name: "session.started" | "turn.started" | "turn.reasoning" | "turn.toolCall.requested" | "turn.toolCall.completed" | "turn.toolCall.denied" | "turn.completed" | "tool.approval.requested" | "tool.approval.resolved";
|
|
356
|
+
name: "session.started" | "turn.started" | "turn.reasoning" | "turn.toolCall.requested" | "turn.toolCall.completed" | "turn.toolCall.denied" | "turn.completed" | "tool.approval.requested" | "tool.approval.resolved" | "sandbox.timeout";
|
|
109
357
|
payload?: string;
|
|
110
358
|
}>, Name>;
|
|
111
359
|
requestToolCall: FunctionReference<"mutation", "internal", {
|
|
@@ -127,7 +375,10 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
127
375
|
agentId: string;
|
|
128
376
|
createdBy: string;
|
|
129
377
|
orgId: string;
|
|
130
|
-
},
|
|
378
|
+
}, {
|
|
379
|
+
sessionId: string;
|
|
380
|
+
workflowId: string;
|
|
381
|
+
}, Name>;
|
|
131
382
|
};
|
|
132
383
|
toolApprovals: {
|
|
133
384
|
respond: FunctionReference<"mutation", "internal", {
|
|
@@ -138,5 +389,98 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
138
389
|
updatePolicy?: "always" | "once" | "never";
|
|
139
390
|
}, null, Name>;
|
|
140
391
|
};
|
|
392
|
+
vpConnection: {
|
|
393
|
+
get: FunctionReference<"query", "internal", {
|
|
394
|
+
agentId: string;
|
|
395
|
+
orgId: string;
|
|
396
|
+
}, {
|
|
397
|
+
_creationTime: number;
|
|
398
|
+
_id: string;
|
|
399
|
+
agentId: string;
|
|
400
|
+
createdAt: number;
|
|
401
|
+
memoryEnabled: boolean;
|
|
402
|
+
messagesEnabled: boolean;
|
|
403
|
+
notesEnabled: boolean;
|
|
404
|
+
orgId: string;
|
|
405
|
+
tasksEnabled: boolean;
|
|
406
|
+
updatedAt: number;
|
|
407
|
+
} | null, Name>;
|
|
408
|
+
getToggles: FunctionReference<"query", "internal", {
|
|
409
|
+
agentId: string;
|
|
410
|
+
orgId: string;
|
|
411
|
+
}, {
|
|
412
|
+
memoryEnabled: boolean;
|
|
413
|
+
messagesEnabled: boolean;
|
|
414
|
+
notesEnabled: boolean;
|
|
415
|
+
tasksEnabled: boolean;
|
|
416
|
+
}, Name>;
|
|
417
|
+
invokeVpTool: FunctionReference<"action", "internal", {
|
|
418
|
+
agentId: string;
|
|
419
|
+
argsJson: string;
|
|
420
|
+
orgId: string;
|
|
421
|
+
tool: "memory" | "tasks" | "messages" | "notes";
|
|
422
|
+
vpFunctionHandle: string;
|
|
423
|
+
}, null, Name>;
|
|
424
|
+
setToggles: FunctionReference<"mutation", "internal", {
|
|
425
|
+
agentId: string;
|
|
426
|
+
memoryEnabled?: boolean;
|
|
427
|
+
messagesEnabled?: boolean;
|
|
428
|
+
notesEnabled?: boolean;
|
|
429
|
+
orgId: string;
|
|
430
|
+
tasksEnabled?: boolean;
|
|
431
|
+
}, string, Name>;
|
|
432
|
+
};
|
|
433
|
+
wakeup: {
|
|
434
|
+
cancel: FunctionReference<"mutation", "internal", {
|
|
435
|
+
orgId: string;
|
|
436
|
+
wakeableWorkId: string;
|
|
437
|
+
}, null, Name>;
|
|
438
|
+
enqueue: FunctionReference<"action", "internal", {
|
|
439
|
+
agentId: string;
|
|
440
|
+
awaitedEventName: string;
|
|
441
|
+
cost: number;
|
|
442
|
+
orgId: string;
|
|
443
|
+
payload?: string;
|
|
444
|
+
reason: string;
|
|
445
|
+
scope: string;
|
|
446
|
+
workFunctionHandle: string;
|
|
447
|
+
workflowId: string;
|
|
448
|
+
}, string, Name>;
|
|
449
|
+
getStatus: FunctionReference<"query", "internal", {
|
|
450
|
+
orgId: string;
|
|
451
|
+
wakeableWorkId: string;
|
|
452
|
+
}, {
|
|
453
|
+
resultSummary?: string;
|
|
454
|
+
status: "pending" | "completed" | "failed" | "cancelled";
|
|
455
|
+
}, Name>;
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
testFixtures: {
|
|
459
|
+
delegationDemoWorkflow: {
|
|
460
|
+
start: FunctionReference<"mutation", "internal", {
|
|
461
|
+
awaitedEventName: string;
|
|
462
|
+
orgId: string;
|
|
463
|
+
}, {
|
|
464
|
+
workflowId: string;
|
|
465
|
+
}, Name>;
|
|
466
|
+
};
|
|
467
|
+
sandboxDemoWorkflow: {
|
|
468
|
+
start: FunctionReference<"mutation", "internal", {
|
|
469
|
+
awaitedEventName: string;
|
|
470
|
+
orgId: string;
|
|
471
|
+
}, {
|
|
472
|
+
resultId: string;
|
|
473
|
+
workflowId: string;
|
|
474
|
+
}, Name>;
|
|
475
|
+
};
|
|
476
|
+
wakeupDemoWorkflow: {
|
|
477
|
+
start: FunctionReference<"mutation", "internal", {
|
|
478
|
+
awaitedEventName: string;
|
|
479
|
+
orgId: string;
|
|
480
|
+
}, {
|
|
481
|
+
resultId: string;
|
|
482
|
+
workflowId: string;
|
|
483
|
+
}, Name>;
|
|
484
|
+
};
|
|
141
485
|
};
|
|
142
486
|
};
|
|
@@ -2,6 +2,9 @@ import { defineComponent } from "convex/server";
|
|
|
2
2
|
import workflow from "@convex-dev/workflow/convex.config";
|
|
3
3
|
import workpool from "@convex-dev/workpool/convex.config";
|
|
4
4
|
import agent from "@convex-dev/agent/convex.config";
|
|
5
|
+
import rateLimiter from "@convex-dev/rate-limiter/convex.config";
|
|
6
|
+
import shardedCounter from "@convex-dev/sharded-counter/convex.config";
|
|
7
|
+
import crons from "@convex-dev/crons/convex.config";
|
|
5
8
|
// @vantageos/agent-engine — Convex COMPONENT definition (pattern
|
|
6
9
|
// `@convex-dev/*`, verified against the published shape of
|
|
7
10
|
// `@convex-dev/workflow` — `defineComponent(name)` + a `convex.config.ts`
|
|
@@ -32,9 +35,25 @@ import agent from "@convex-dev/agent/convex.config";
|
|
|
32
35
|
// awaitEventTimeouts, wakeableWork) is deliberately NOT yet re-hosted
|
|
33
36
|
// here — porting those without a working component-level test harness
|
|
34
37
|
// behind each of them would violate Day 128 (never ship unverified).
|
|
38
|
+
// C3 (this pass): mandates ("notre ligne", autorité bornée) are now hosted
|
|
39
|
+
// under this component boundary, following the exact same trio the
|
|
40
|
+
// repo-root prototype used (I0 §3, `convex/convex.config.ts`) -- official
|
|
41
|
+
// `@convex-dev/*` libraries only, NO canary/alpha dependency for a
|
|
42
|
+
// guardrail: `rate-limiter` for the fails-closed spend gate itself,
|
|
43
|
+
// `sharded-counter` for the usage rollup. See component/engine/mandates.ts.
|
|
44
|
+
// C4 (this pass): habits ("notre ligne", un cron DYNAMIQUE par agent/org)
|
|
45
|
+
// are now hosted under this component boundary, ported byte-identical from
|
|
46
|
+
// the repo-root prototype (convex/habits.ts). `crons` is a sub-component of
|
|
47
|
+
// THIS component -- create/updateSchedule/enable/disable register or tear
|
|
48
|
+
// down a runtime cron job via `@convex-dev/crons` inside the SAME Convex
|
|
49
|
+
// mutation transaction that writes the `habits` row, so no habit schedule
|
|
50
|
+
// change ever requires a redeploy. See component/engine/habits.ts.
|
|
35
51
|
const component = defineComponent("agentEngine");
|
|
36
52
|
component.use(workflow);
|
|
37
53
|
component.use(workpool, { name: "agentTurnPool" });
|
|
38
54
|
component.use(workpool, { name: "wakeupPool" });
|
|
39
55
|
component.use(agent);
|
|
56
|
+
component.use(rateLimiter);
|
|
57
|
+
component.use(shardedCounter);
|
|
58
|
+
component.use(crons);
|
|
40
59
|
export default component;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export declare const create: import("convex/server").RegisteredMutation<"public", {
|
|
2
|
+
description?: string | undefined;
|
|
3
|
+
reasoningEffort?: "none" | "low" | "medium" | "high" | undefined;
|
|
4
|
+
modelProvider?: "gateway" | "openrouter" | undefined;
|
|
5
|
+
maxSubagents?: number | undefined;
|
|
6
|
+
maxInputTokensPerSession?: number | false | undefined;
|
|
2
7
|
name: string;
|
|
3
8
|
orgId: string;
|
|
4
9
|
instructions: string;
|
|
@@ -11,6 +16,11 @@ export declare const get: import("convex/server").RegisteredQuery<"public", {
|
|
|
11
16
|
}, Promise<{
|
|
12
17
|
_id: import("convex/values").GenericId<"agents">;
|
|
13
18
|
_creationTime: number;
|
|
19
|
+
description?: string | undefined;
|
|
20
|
+
reasoningEffort?: "none" | "low" | "medium" | "high" | undefined;
|
|
21
|
+
modelProvider?: "gateway" | "openrouter" | undefined;
|
|
22
|
+
maxSubagents?: number | undefined;
|
|
23
|
+
maxInputTokensPerSession?: number | false | undefined;
|
|
14
24
|
name: string;
|
|
15
25
|
orgId: string;
|
|
16
26
|
status: "draft" | "live" | "archived";
|
|
@@ -8,13 +8,21 @@ import { requireOrgId } from "../lib/auth.js";
|
|
|
8
8
|
// `create`/`get`, no `update`/`list`/skills/connections — the full agent
|
|
9
9
|
// aggregate CRUD stays out of this component boundary for this pass (see
|
|
10
10
|
// component/schema.ts SCOPE note).
|
|
11
|
+
const reasoningEffort = v.union(v.literal("none"), v.literal("low"), v.literal("medium"), v.literal("high"));
|
|
12
|
+
const modelProvider = v.union(v.literal("gateway"), v.literal("openrouter"));
|
|
13
|
+
const maxInputTokensPerSession = v.union(v.number(), v.literal(false));
|
|
11
14
|
const agentDoc = v.object({
|
|
12
15
|
_id: v.id("agents"),
|
|
13
16
|
_creationTime: v.number(),
|
|
14
17
|
orgId: v.string(),
|
|
15
18
|
name: v.string(),
|
|
19
|
+
description: v.optional(v.string()),
|
|
16
20
|
instructions: v.string(),
|
|
17
21
|
model: v.string(),
|
|
22
|
+
reasoningEffort: v.optional(reasoningEffort),
|
|
23
|
+
modelProvider: v.optional(modelProvider),
|
|
24
|
+
maxSubagents: v.optional(v.number()),
|
|
25
|
+
maxInputTokensPerSession: v.optional(maxInputTokensPerSession),
|
|
18
26
|
status: v.union(v.literal("draft"), v.literal("live"), v.literal("archived")),
|
|
19
27
|
createdBy: v.string(),
|
|
20
28
|
createdAt: v.number(),
|
|
@@ -25,8 +33,13 @@ export const create = mutation({
|
|
|
25
33
|
orgId: v.string(),
|
|
26
34
|
createdBy: v.string(),
|
|
27
35
|
name: v.string(),
|
|
36
|
+
description: v.optional(v.string()),
|
|
28
37
|
instructions: v.string(),
|
|
29
38
|
model: v.string(),
|
|
39
|
+
reasoningEffort: v.optional(reasoningEffort),
|
|
40
|
+
modelProvider: v.optional(modelProvider),
|
|
41
|
+
maxSubagents: v.optional(v.number()),
|
|
42
|
+
maxInputTokensPerSession: v.optional(maxInputTokensPerSession),
|
|
30
43
|
},
|
|
31
44
|
returns: v.id("agents"),
|
|
32
45
|
handler: async (ctx, args) => {
|
|
@@ -43,12 +56,20 @@ export const create = mutation({
|
|
|
43
56
|
if (args.model.trim().length === 0) {
|
|
44
57
|
throw new Error("Validation: model must not be empty");
|
|
45
58
|
}
|
|
59
|
+
if (args.maxSubagents !== undefined && args.maxSubagents < 0) {
|
|
60
|
+
throw new Error("Validation: maxSubagents must not be negative");
|
|
61
|
+
}
|
|
46
62
|
const now = Date.now();
|
|
47
63
|
return await ctx.db.insert("agents", {
|
|
48
64
|
orgId,
|
|
49
65
|
name: args.name,
|
|
66
|
+
description: args.description,
|
|
50
67
|
instructions: args.instructions,
|
|
51
68
|
model: args.model,
|
|
69
|
+
reasoningEffort: args.reasoningEffort,
|
|
70
|
+
modelProvider: args.modelProvider,
|
|
71
|
+
maxSubagents: args.maxSubagents,
|
|
72
|
+
maxInputTokensPerSession: args.maxInputTokensPerSession,
|
|
52
73
|
status: "live",
|
|
53
74
|
createdBy: args.createdBy,
|
|
54
75
|
createdAt: now,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const schedule: import("convex/server").RegisteredMutation<"public", {
|
|
2
|
+
orgId: string;
|
|
3
|
+
sessionId: import("convex/values").GenericId<"sessions">;
|
|
4
|
+
awaitedEventName: string;
|
|
5
|
+
timeoutMs: number;
|
|
6
|
+
}, Promise<import("convex/values").GenericId<"awaitEventTimeouts">>>;
|
|
7
|
+
export declare const cancel: import("convex/server").RegisteredMutation<"public", {
|
|
8
|
+
orgId: string;
|
|
9
|
+
timeoutRowId: import("convex/values").GenericId<"awaitEventTimeouts">;
|
|
10
|
+
}, Promise<null>>;
|
|
11
|
+
export declare const fire: import("convex/server").RegisteredMutation<"internal", {
|
|
12
|
+
timeoutRowId: import("convex/values").GenericId<"awaitEventTimeouts">;
|
|
13
|
+
}, Promise<null>>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { internal } from "../_generated/api.js";
|
|
3
|
+
import { internalMutation, mutation } from "../_generated/server.js";
|
|
4
|
+
import { assertSameOrg, requireOrgId } from "../lib/auth.js";
|
|
5
|
+
// engine/awaitEventTimeout — self-built timeout for step.awaitEvent
|
|
6
|
+
// (workflow#177: "Convex does not provide a native timeout for
|
|
7
|
+
// awaitEvent"). PORTED from convex/engine/awaitEventTimeout.ts (repo-root
|
|
8
|
+
// prototype) into the component boundary (C2). We schedule a mutation that
|
|
9
|
+
// fires a "blank" `sandbox.timeout` sessionEvent at the deadline; the
|
|
10
|
+
// workflow's `awaitEvent` call is written to also accept this event name so
|
|
11
|
+
// it wakes up even if the awaited event never arrives. Pattern:
|
|
12
|
+
// maintainer's posted code in workflow#177, adapted to our sessionEvents
|
|
13
|
+
// table.
|
|
14
|
+
//
|
|
15
|
+
// C2 MIGRATION NOTE ("notre ligne"): orgId is an EXPLICIT ARGUMENT on
|
|
16
|
+
// every public function, never derived from `ctx.auth` -- auth does NOT
|
|
17
|
+
// propagate across a component boundary (component/lib/auth.ts). Also:
|
|
18
|
+
// `sessionEvents.name`'s union in component/schema.ts did not previously
|
|
19
|
+
// include `sandbox.timeout` -- it has been added there (and mirrored in
|
|
20
|
+
// `engine/sessions.listEvents`'s return validator) as part of this
|
|
21
|
+
// migration, otherwise `fire`'s insert below would not compile under the
|
|
22
|
+
// strict build.
|
|
23
|
+
export const schedule = mutation({
|
|
24
|
+
args: {
|
|
25
|
+
orgId: v.string(),
|
|
26
|
+
sessionId: v.id("sessions"),
|
|
27
|
+
awaitedEventName: v.string(),
|
|
28
|
+
timeoutMs: v.number(),
|
|
29
|
+
},
|
|
30
|
+
returns: v.id("awaitEventTimeouts"),
|
|
31
|
+
handler: async (ctx, args) => {
|
|
32
|
+
const orgId = requireOrgId(args.orgId);
|
|
33
|
+
const session = await ctx.db.get(args.sessionId);
|
|
34
|
+
assertSameOrg(orgId, session, "Session not found");
|
|
35
|
+
if (args.timeoutMs <= 0) {
|
|
36
|
+
throw new Error("Validation: timeoutMs must be > 0");
|
|
37
|
+
}
|
|
38
|
+
const timeoutRowId = await ctx.db.insert("awaitEventTimeouts", {
|
|
39
|
+
orgId,
|
|
40
|
+
sessionId: args.sessionId,
|
|
41
|
+
awaitedEventName: args.awaitedEventName,
|
|
42
|
+
deadlineAt: Date.now() + args.timeoutMs,
|
|
43
|
+
});
|
|
44
|
+
const scheduledFunctionId = await ctx.scheduler.runAfter(args.timeoutMs, internal.engine.awaitEventTimeout.fire, { timeoutRowId });
|
|
45
|
+
await ctx.db.patch(timeoutRowId, { scheduledFunctionId });
|
|
46
|
+
return timeoutRowId;
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
export const cancel = mutation({
|
|
50
|
+
args: { orgId: v.string(), timeoutRowId: v.id("awaitEventTimeouts") },
|
|
51
|
+
returns: v.null(),
|
|
52
|
+
handler: async (ctx, args) => {
|
|
53
|
+
const orgId = requireOrgId(args.orgId);
|
|
54
|
+
const row = await ctx.db.get(args.timeoutRowId);
|
|
55
|
+
assertSameOrg(orgId, row, "Timeout not found");
|
|
56
|
+
if (!row.firedAt && !row.cancelledAt && row.scheduledFunctionId) {
|
|
57
|
+
await ctx.scheduler.cancel(row.scheduledFunctionId);
|
|
58
|
+
await ctx.db.patch(args.timeoutRowId, { cancelledAt: Date.now() });
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
// internal — invoked only by the scheduler, never by a client.
|
|
64
|
+
export const fire = internalMutation({
|
|
65
|
+
args: { timeoutRowId: v.id("awaitEventTimeouts") },
|
|
66
|
+
returns: v.null(),
|
|
67
|
+
handler: async (ctx, args) => {
|
|
68
|
+
const row = await ctx.db.get(args.timeoutRowId);
|
|
69
|
+
if (!row || row.firedAt || row.cancelledAt) {
|
|
70
|
+
return null; // already resolved by the real event or by a prior fire
|
|
71
|
+
}
|
|
72
|
+
await ctx.db.patch(args.timeoutRowId, { firedAt: Date.now() });
|
|
73
|
+
await ctx.db.insert("sessionEvents", {
|
|
74
|
+
orgId: row.orgId,
|
|
75
|
+
sessionId: row.sessionId,
|
|
76
|
+
name: "sandbox.timeout",
|
|
77
|
+
payload: JSON.stringify({ awaitedEventName: row.awaitedEventName }),
|
|
78
|
+
createdAt: Date.now(),
|
|
79
|
+
});
|
|
80
|
+
return null;
|
|
81
|
+
},
|
|
82
|
+
});
|