@vantageos/agent-engine 0.1.0-alpha.1 → 0.1.0-alpha.3
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 +198 -17
- package/dist/component/_generated/api.d.ts +50 -0
- package/dist/component/_generated/api.js +30 -0
- package/dist/component/_generated/component.d.ts +124 -0
- package/dist/component/_generated/component.js +10 -0
- package/dist/component/_generated/dataModel.d.ts +45 -0
- package/dist/component/_generated/dataModel.js +10 -0
- package/dist/component/_generated/server.d.ts +120 -0
- package/dist/component/_generated/server.js +77 -0
- package/dist/component/convex.config.js +19 -21
- package/dist/component/engine/agents.d.ts +19 -0
- package/dist/component/engine/agents.js +67 -0
- package/dist/component/engine/durableJob.d.ts +43 -0
- package/dist/component/engine/durableJob.js +262 -0
- package/dist/component/engine/resolvers.d.ts +12 -0
- package/dist/component/engine/resolvers.js +50 -0
- package/dist/component/engine/sessions.d.ts +36 -0
- package/dist/component/engine/sessions.js +233 -0
- package/dist/component/engine/toolApprovals.d.ts +5 -0
- package/dist/component/engine/toolApprovals.js +51 -0
- package/dist/component/lib/auth.d.ts +7 -0
- package/dist/component/lib/auth.js +24 -0
- package/dist/component/schema.d.ts +124 -0
- package/dist/component/schema.js +130 -0
- package/dist/component/testFixtures/callerSteps.d.ts +20 -0
- package/dist/component/testFixtures/callerSteps.js +90 -0
- package/package.json +8 -1
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import { internalMutation, internalQuery } from "../_generated/server";
|
|
3
|
+
// testFixtures/callerSteps — stand-ins for a CALLER'S OWN step function
|
|
4
|
+
// (the thing a real consumer, e.g. VantagePeers, would define in ITS OWN
|
|
5
|
+
// app and pass to `engine/durableJob.start` as `stepFunctionHandle` via
|
|
6
|
+
// `createFunctionHandle`). These exist ONLY to drive the contract tests in
|
|
7
|
+
// convex/engineDurableJob.test.ts -- they are not part of the public
|
|
8
|
+
// surface (see examples/vantage-peers-long-task for the real, documented
|
|
9
|
+
// integration a consumer would write).
|
|
10
|
+
//
|
|
11
|
+
// Attempt counts are tracked IN-MEMORY (module-level Map), not via a DB
|
|
12
|
+
// write, because a mutation that throws rolls back every write made in its
|
|
13
|
+
// OWN transaction -- including a "record that I was called" insert made
|
|
14
|
+
// just before the throw. In-memory state survives the rollback since it is
|
|
15
|
+
// plain JS state, not part of the Convex transaction.
|
|
16
|
+
const attemptCounts = new Map();
|
|
17
|
+
function bump(jobId, stepIndex) {
|
|
18
|
+
const key = `${jobId}:${stepIndex}`;
|
|
19
|
+
const next = (attemptCounts.get(key) ?? 0) + 1;
|
|
20
|
+
attemptCounts.set(key, next);
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
export const getAttemptCount = internalQuery({
|
|
24
|
+
args: { jobId: v.id("durableJobs"), stepIndex: v.number() },
|
|
25
|
+
returns: v.number(),
|
|
26
|
+
handler: async (_ctx, args) => {
|
|
27
|
+
return attemptCounts.get(`${args.jobId}:${args.stepIndex}`) ?? 0;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
// TEST-ONLY: `convexTest()` reuses deterministic, low-cardinality document
|
|
31
|
+
// IDs across SEPARATE test instances within the same process, so this
|
|
32
|
+
// module-level Map must be cleared between tests to avoid one test's
|
|
33
|
+
// counters leaking into the next via a colliding `${jobId}:${stepIndex}`
|
|
34
|
+
// key. Called from `beforeEach` in engineDurableJob.test.ts.
|
|
35
|
+
export const resetAttemptCounts = internalMutation({
|
|
36
|
+
args: {},
|
|
37
|
+
returns: v.null(),
|
|
38
|
+
handler: async () => {
|
|
39
|
+
attemptCounts.clear();
|
|
40
|
+
return null;
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
// Records one row per SUCCESSFUL invocation so tests can assert exactly
|
|
44
|
+
// which step indices actually completed (idempotent-replay assertions).
|
|
45
|
+
export const alwaysSucceeds = internalMutation({
|
|
46
|
+
args: { orgId: v.string(), jobId: v.id("durableJobs"), stepIndex: v.number() },
|
|
47
|
+
returns: v.null(),
|
|
48
|
+
handler: async (ctx, args) => {
|
|
49
|
+
bump(args.jobId, args.stepIndex);
|
|
50
|
+
await ctx.db.insert("callerStepInvocations", {
|
|
51
|
+
orgId: args.orgId,
|
|
52
|
+
jobId: args.jobId,
|
|
53
|
+
stepIndex: args.stepIndex,
|
|
54
|
+
createdAt: Date.now(),
|
|
55
|
+
});
|
|
56
|
+
return null;
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
// Fails on every attempt -- used to prove "abandon after N échecs". Attempt
|
|
60
|
+
// count is observable via `getAttemptCount` even though every DB write this
|
|
61
|
+
// function might otherwise make would be rolled back by the throw.
|
|
62
|
+
export const alwaysFails = internalMutation({
|
|
63
|
+
args: { orgId: v.string(), jobId: v.id("durableJobs"), stepIndex: v.number() },
|
|
64
|
+
returns: v.null(),
|
|
65
|
+
handler: async (_ctx, args) => {
|
|
66
|
+
bump(args.jobId, args.stepIndex);
|
|
67
|
+
throw new Error(`simulated failure at step ${args.stepIndex}`);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
// Fails on the FIRST attempt of ANY step, then succeeds on every
|
|
71
|
+
// subsequent attempt of that same step -- used to prove retry-then-succeed
|
|
72
|
+
// still advances the cursor (not just outright failure), exercising the
|
|
73
|
+
// `maxAttemptsPerStep > 1` path distinctly from `alwaysFails`.
|
|
74
|
+
export const failsFirstAttemptThenSucceeds = internalMutation({
|
|
75
|
+
args: { orgId: v.string(), jobId: v.id("durableJobs"), stepIndex: v.number() },
|
|
76
|
+
returns: v.null(),
|
|
77
|
+
handler: async (ctx, args) => {
|
|
78
|
+
const attemptNumber = bump(args.jobId, args.stepIndex);
|
|
79
|
+
if (attemptNumber === 1) {
|
|
80
|
+
throw new Error(`simulated single failure at step ${args.stepIndex}`);
|
|
81
|
+
}
|
|
82
|
+
await ctx.db.insert("callerStepInvocations", {
|
|
83
|
+
orgId: args.orgId,
|
|
84
|
+
jobId: args.jobId,
|
|
85
|
+
stepIndex: args.stepIndex,
|
|
86
|
+
createdAt: Date.now(),
|
|
87
|
+
});
|
|
88
|
+
return null;
|
|
89
|
+
},
|
|
90
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vantageos/agent-engine",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
4
|
"description": "Reusable Convex component: durable agent engine. Agent = data aggregate (root sheet + child tables), never compiled code. Built on @convex-dev/workflow + @convex-dev/workpool (+ @convex-dev/agent). Eve parity by design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -21,6 +21,9 @@
|
|
|
21
21
|
"./convex.config.js": {
|
|
22
22
|
"types": "./dist/component/convex.config.d.ts",
|
|
23
23
|
"default": "./dist/component/convex.config.js"
|
|
24
|
+
},
|
|
25
|
+
"./_generated/component.js": {
|
|
26
|
+
"types": "./dist/component/_generated/component.d.ts"
|
|
24
27
|
}
|
|
25
28
|
},
|
|
26
29
|
"scripts": {
|
|
@@ -35,6 +38,10 @@
|
|
|
35
38
|
},
|
|
36
39
|
"dependencies": {
|
|
37
40
|
"@convex-dev/agent": "0.6.4",
|
|
41
|
+
"@convex-dev/aggregate": "^0.2.2",
|
|
42
|
+
"@convex-dev/crons": "^0.2.2",
|
|
43
|
+
"@convex-dev/rate-limiter": "^0.3.2",
|
|
44
|
+
"@convex-dev/sharded-counter": "^0.2.1",
|
|
38
45
|
"@convex-dev/workflow": "0.4.4",
|
|
39
46
|
"@convex-dev/workpool": "0.4.7",
|
|
40
47
|
"ai": "6.0.35",
|