@vantageos/agent-engine 0.1.0-alpha.6 → 0.1.0-alpha.8
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/LICENSE +110 -0
- package/README.md +231 -661
- package/dist/component/convex.config.js +8 -9
- package/dist/component/engine/awaitEventTimeout.js +2 -3
- package/dist/component/engine/delegation.js +14 -16
- package/dist/component/engine/directory.js +1 -1
- package/dist/component/engine/durableJob.js +6 -6
- package/dist/component/engine/habits.js +8 -9
- package/dist/component/engine/mandates.js +6 -7
- package/dist/component/engine/sandboxCallback.js +8 -11
- package/dist/component/engine/sessions.js +8 -9
- package/dist/component/engine/toolApprovals.js +1 -1
- package/dist/component/engine/vpConnection.js +6 -9
- package/dist/component/engine/wakeup.js +18 -20
- package/dist/component/engine/workflows.js +4 -7
- package/dist/component/schema.js +42 -67
- package/dist/component/testFixtures/callerSteps.js +1 -1
- package/dist/component/testFixtures/delegationDemoWorkflow.js +2 -3
- package/dist/component/testFixtures/sandboxDemoWorkflow.js +2 -2
- package/dist/component/testFixtures/wakeupDemoWorkflow.js +2 -2
- package/package.json +16 -5
package/dist/component/schema.js
CHANGED
|
@@ -8,8 +8,8 @@ import { v } from "convex/values";
|
|
|
8
8
|
// root, which only backs THIS repo's own dev/test deployment.
|
|
9
9
|
//
|
|
10
10
|
// SCOPE (T2-QUATER: durableJob only. T2-QUINQUIES, this pass: WIDENS the
|
|
11
|
-
// boundary to the SESSIONS surface
|
|
12
|
-
//
|
|
11
|
+
// boundary to the SESSIONS surface a downstream conversation-thread
|
|
12
|
+
// consumer needs — session start/turn, streamed reasoning/tool-call events,
|
|
13
13
|
// toolApprovals response, replay on reconnect, dynamic resolver — see
|
|
14
14
|
// README "What's callable"). Still DELIBERATELY NARROW: `skills`,
|
|
15
15
|
// `connections`, `subagents`, `habits`, `sandboxConfig`, `modelKeys`,
|
|
@@ -20,10 +20,8 @@ import { v } from "convex/values";
|
|
|
20
20
|
// can read (component isolation: this package cannot read a consumer app's
|
|
21
21
|
// OWN `agents` table across the component boundary).
|
|
22
22
|
export default defineSchema({
|
|
23
|
-
// durableJobs — GENERIC durable step-batch primitive
|
|
24
|
-
//
|
|
25
|
-
// contract description; this table definition is byte-identical to the
|
|
26
|
-
// one there.
|
|
23
|
+
// durableJobs — GENERIC durable step-batch primitive. See
|
|
24
|
+
// engine/durableJob.ts for the full contract description.
|
|
27
25
|
durableJobs: defineTable({
|
|
28
26
|
orgId: v.string(),
|
|
29
27
|
kind: v.string(),
|
|
@@ -69,9 +67,9 @@ export default defineSchema({
|
|
|
69
67
|
instructions: v.string(),
|
|
70
68
|
model: v.string(),
|
|
71
69
|
reasoningEffort: v.optional(v.union(v.literal("none"), v.literal("low"), v.literal("medium"), v.literal("high"))), // eve: agent-definition.ts:315-319
|
|
72
|
-
modelProvider: v.optional(v.union(v.literal("gateway"), v.literal("openrouter"))), //
|
|
73
|
-
maxSubagents: v.optional(v.number()), // eve: agent-definition.ts:163-179,
|
|
74
|
-
maxInputTokensPerSession: v.optional(v.union(v.number(), v.literal(false))), // eve: :195, false =
|
|
70
|
+
modelProvider: v.optional(v.union(v.literal("gateway"), v.literal("openrouter"))), // intentional divergence from Eve (bring-your-own-key); optional so it stays additive/backwards-compatible with rows created before this field existed
|
|
71
|
+
maxSubagents: v.optional(v.number()), // eve: agent-definition.ts:163-179, default 100
|
|
72
|
+
maxInputTokensPerSession: v.optional(v.union(v.number(), v.literal(false))), // eve: :195, false = unlimited
|
|
75
73
|
status: v.union(v.literal("draft"), v.literal("live"), v.literal("archived")),
|
|
76
74
|
createdBy: v.string(),
|
|
77
75
|
createdAt: v.number(),
|
|
@@ -95,21 +93,12 @@ export default defineSchema({
|
|
|
95
93
|
.index("by_org", ["orgId"])
|
|
96
94
|
.index("by_org_agent", ["orgId", "agentId"])
|
|
97
95
|
.index("by_org_agent_tool", ["orgId", "agentId", "toolName"]),
|
|
98
|
-
// sessions — one conversation container per `sessions.start` call.
|
|
99
|
-
//
|
|
100
|
-
// run (
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
// with its own step function. This is a deliberate divergence ("notre
|
|
105
|
-
// ligne") from the app-level prototype, narrowing the shipped surface to
|
|
106
|
-
// what has a working component-level test harness behind it.
|
|
107
|
-
// C1.5 ("notre ligne", measured trou fixed): sessions ARE now piloted by
|
|
108
|
-
// a versioned `@convex-dev/workflow` run (component/engine/workflows.ts:
|
|
109
|
-
// sessionWorkflowV1) -- the divergence note above (T2-QUINQUIES,
|
|
110
|
-
// "deliberately does NOT tie a session to a workflow run") is retired.
|
|
111
|
-
// `workflowId`/`workflowVersion` are optional so pre-C1.5 rows (written
|
|
112
|
-
// before this migration) remain valid without a backfill.
|
|
96
|
+
// sessions — one conversation container per `sessions.start` call.
|
|
97
|
+
// "intentional divergence from Eve": a session is piloted by a VERSIONED
|
|
98
|
+
// `@convex-dev/workflow` run (engine/workflows.ts: sessionWorkflowV1), so
|
|
99
|
+
// a turn survives a deploy. `workflowId`/`workflowVersion` are optional:
|
|
100
|
+
// rows written before that workflow existed stay valid without a backfill,
|
|
101
|
+
// and a consumer driving turns itself may leave them unset.
|
|
113
102
|
sessions: defineTable({
|
|
114
103
|
orgId: v.string(),
|
|
115
104
|
agentId: v.id("agents"),
|
|
@@ -135,16 +124,16 @@ export default defineSchema({
|
|
|
135
124
|
orgId: v.string(),
|
|
136
125
|
sessionId: v.id("sessions"),
|
|
137
126
|
name: v.union(v.literal("session.started"), v.literal("turn.started"), v.literal("turn.reasoning"), v.literal("turn.toolCall.requested"), v.literal("turn.toolCall.completed"),
|
|
138
|
-
// "
|
|
127
|
+
// "intentional divergence from Eve" (VP k17ea6x3tht8xa3rxm139t23gx8ajkf3, defaut 2):
|
|
139
128
|
// explicit terminal state for a one-turn approval REFUSAL, distinct
|
|
140
129
|
// from "turn.toolCall.completed" (tool actually ran). Without this,
|
|
141
130
|
// a denied tool call had no event of its own -- a consumer had no
|
|
142
131
|
// way to tell "refused this turn" from "skipped, turn completed
|
|
143
|
-
// anyway", which is the wrong default
|
|
132
|
+
// anyway", which is the wrong default a consumer had to code around.
|
|
144
133
|
v.literal("turn.toolCall.denied"), v.literal("turn.completed"), v.literal("tool.approval.requested"), v.literal("tool.approval.resolved"),
|
|
145
|
-
//
|
|
134
|
+
// Blank event auto-inserted by `engine/awaitEventTimeout.fire`
|
|
146
135
|
// (workflow#177: Convex provides no native timeout for
|
|
147
|
-
// `step.awaitEvent`). See
|
|
136
|
+
// `step.awaitEvent`). See engine/awaitEventTimeout.ts.
|
|
148
137
|
v.literal("sandbox.timeout")),
|
|
149
138
|
payload: v.optional(v.string()), // JSON-serialized, free contract per event name
|
|
150
139
|
createdAt: v.number(),
|
|
@@ -152,10 +141,8 @@ export default defineSchema({
|
|
|
152
141
|
.index("by_org", ["orgId"])
|
|
153
142
|
.index("by_org_session", ["orgId", "sessionId"]),
|
|
154
143
|
// ---------------------------------------------------------------------
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
// to their app-level source. See component/engine/wakeup.ts and
|
|
158
|
-
// component/engine/awaitEventTimeout.ts for the mechanism itself.
|
|
144
|
+
// WAKE-UP WITHOUT POLLING. See engine/wakeup.ts and
|
|
145
|
+
// engine/awaitEventTimeout.ts for the mechanism itself.
|
|
159
146
|
// ---------------------------------------------------------------------
|
|
160
147
|
// wakeableWork — GENERIC wake-up primitive. `enqueue` puts caller-supplied
|
|
161
148
|
// work (an action, referenced by an opaque function-handle string) into a
|
|
@@ -210,14 +197,11 @@ export default defineSchema({
|
|
|
210
197
|
observedResultSummary: v.optional(v.string()),
|
|
211
198
|
}).index("by_org", ["orgId"]),
|
|
212
199
|
// ---------------------------------------------------------------------
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
// component/engine/mandates.ts and component/engine/wakeup.ts (the C3
|
|
217
|
-
// seam: `enqueue` now funds through `mandates.spendInternal` before any
|
|
218
|
-
// work can enter the wakeup pool).
|
|
200
|
+
// MANDATES — "intentional divergence from Eve": bounded authority. See
|
|
201
|
+
// engine/mandates.ts and engine/wakeup.ts, where `enqueue` funds through
|
|
202
|
+
// `mandates.spendInternal` before any work can enter the wakeup pool.
|
|
219
203
|
// ---------------------------------------------------------------------
|
|
220
|
-
// mandates — a
|
|
204
|
+
// mandates — a cap is a DATA row scoped by orgId + agentId + scope,
|
|
221
205
|
// never a constant read from code. `kind`/`rate`/`period`/`capacity` are
|
|
222
206
|
// the inline contract of @convex-dev/rate-limiter ("dynamic config"): the
|
|
223
207
|
// COST (`count`) is a WEIGHTED count (tokens/euros/calls), never a plain
|
|
@@ -254,12 +238,10 @@ export default defineSchema({
|
|
|
254
238
|
.index("by_org_agent", ["orgId", "agentId"])
|
|
255
239
|
.index("by_org_status", ["orgId", "status"]),
|
|
256
240
|
// ---------------------------------------------------------------------
|
|
257
|
-
//
|
|
258
|
-
// agent/org,
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
// source. See component/engine/habits.ts (the C4 seam: `crons` is a new
|
|
262
|
-
// sub-component of THIS component, registered in component/convex.config.ts).
|
|
241
|
+
// HABITS — "intentional divergence from Eve": a habit is a DYNAMIC cron
|
|
242
|
+
// per agent/org, which is what turns a chat into an employee. See
|
|
243
|
+
// engine/habits.ts; `crons` is a sub-component of THIS component,
|
|
244
|
+
// registered in component/convex.config.ts.
|
|
263
245
|
// ---------------------------------------------------------------------
|
|
264
246
|
// habits — a schedule is a DATA row scoped by orgId + agentId, never a
|
|
265
247
|
// constant read from a deployed `convex/crons.ts`. `cronExpression` is
|
|
@@ -297,16 +279,12 @@ export default defineSchema({
|
|
|
297
279
|
.index("by_org", ["orgId"])
|
|
298
280
|
.index("by_org_habit", ["orgId", "habitId"]),
|
|
299
281
|
// ---------------------------------------------------------------------
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
// Ported from convex/schema.ts (repo-root prototype, sandboxRuns /
|
|
303
|
-
// sandboxCallbackDeliveries / sandboxCallbackDeadLetters); table shapes
|
|
304
|
-
// are byte-identical to their app-level source. See
|
|
305
|
-
// component/engine/sandboxCallback.ts.
|
|
282
|
+
// SANDBOX BRIDGE — the same pause/wake mechanism serves both the sandbox
|
|
283
|
+
// and agent-to-agent delegation. See engine/sandboxCallback.ts.
|
|
306
284
|
//
|
|
307
|
-
//
|
|
308
|
-
// that actually talks to `@vercel/sandbox`
|
|
309
|
-
//
|
|
285
|
+
// BOUNDARY, and why it is where it is: the "use node" action
|
|
286
|
+
// that actually talks to `@vercel/sandbox` CANNOT live inside this
|
|
287
|
+
// component — the
|
|
310
288
|
// Convex CLI's own component bundler HARD-CRASHES on any "use node" file
|
|
311
289
|
// found in a child component directory ("use node directive is not
|
|
312
290
|
// supported in components", node_modules/convex/dist/cjs/cli/lib/
|
|
@@ -367,15 +345,12 @@ export default defineSchema({
|
|
|
367
345
|
createdAt: v.number(),
|
|
368
346
|
}).index("by_org", ["orgId"]),
|
|
369
347
|
// ---------------------------------------------------------------------
|
|
370
|
-
//
|
|
371
|
-
//
|
|
372
|
-
//
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
// (the C6 seam: both terminate delegation/clone paths in exactly one call
|
|
377
|
-
// to THIS component's own `engine/wakeup.enqueue`, C2/C3's public action,
|
|
378
|
-
// never a second onComplete/sendEvent path).
|
|
348
|
+
// DELEGATION — an agent delegating to another agent uses THE SAME
|
|
349
|
+
// pause/wake system as the sandbox bridge: one system to maintain, not
|
|
350
|
+
// two. See engine/delegation.ts and engine/vpConnection.ts: every
|
|
351
|
+
// delegation/clone path terminates in exactly one call to this
|
|
352
|
+
// component's own public `engine/wakeup.enqueue`, never in a second
|
|
353
|
+
// onComplete/sendEvent path.
|
|
379
354
|
// ---------------------------------------------------------------------
|
|
380
355
|
// subagents — declared subagents, RECURSIVE (the child is a full
|
|
381
356
|
// `agents` row with its own aggregate). Isolation is by construction
|
|
@@ -395,7 +370,7 @@ export default defineSchema({
|
|
|
395
370
|
.index("by_org", ["orgId"])
|
|
396
371
|
.index("by_org_parent", ["orgId", "parentAgentId"])
|
|
397
372
|
.index("by_org_child", ["orgId", "childAgentId"])
|
|
398
|
-
//
|
|
373
|
+
// Build-time collision guard (engine/delegation.declareSubagent):
|
|
399
374
|
// exact-match lookup of an existing (parent, toolName) pair, no filter().
|
|
400
375
|
.index("by_org_parent_tool", ["orgId", "parentAgentId", "toolName"]),
|
|
401
376
|
// delegationRuns — one row per A->B delegation through a declared
|
|
@@ -421,7 +396,7 @@ export default defineSchema({
|
|
|
421
396
|
.index("by_org_parent", ["orgId", "parentAgentId"])
|
|
422
397
|
.index("by_org_workflow", ["orgId", "workflowId"])
|
|
423
398
|
.index("by_org_awaitedEvent", ["orgId", "awaitedEventName"]),
|
|
424
|
-
// agentCloneRuns —
|
|
399
|
+
// agentCloneRuns — the built-in `agent` tool (eve.dev/docs/subagents: "the
|
|
425
400
|
// built-in `agent` tool clones the ROOT, root-only, NOT recursive -- it
|
|
426
401
|
// cannot call itself"). `viaAgentTool` is the recursion guard: a clone
|
|
427
402
|
// invocation started BY a clone invocation (viaAgentTool: true passed in)
|
|
@@ -441,9 +416,9 @@ export default defineSchema({
|
|
|
441
416
|
})
|
|
442
417
|
.index("by_org", ["orgId"])
|
|
443
418
|
.index("by_org_agent", ["orgId", "agentId"]),
|
|
444
|
-
// vpConnections —
|
|
419
|
+
// vpConnections — teamwork. The
|
|
445
420
|
// four VantagePeers tools (memory, tasks, messages, notes) wired as a
|
|
446
|
-
// CONNECTION of the agent aggregate,
|
|
421
|
+
// CONNECTION of the agent aggregate, an intentional divergence from Eve. 0..1 row per agent;
|
|
447
422
|
// absence means "use the defaults" (all four ON) -- see
|
|
448
423
|
// `engine/vpConnection.ts:defaultToggles`. DIRECT access: invocation
|
|
449
424
|
// goes through a caller-supplied Convex function handle
|
|
@@ -56,7 +56,7 @@ export const alwaysSucceeds = internalMutation({
|
|
|
56
56
|
return null;
|
|
57
57
|
},
|
|
58
58
|
});
|
|
59
|
-
// Fails on every attempt -- used to prove
|
|
59
|
+
// Fails on every attempt -- used to prove abandonment after N failures. Attempt
|
|
60
60
|
// count is observable via `getAttemptCount` even though every DB write this
|
|
61
61
|
// function might otherwise make would be rolled back by the throw.
|
|
62
62
|
export const alwaysFails = internalMutation({
|
|
@@ -4,14 +4,13 @@ import { components, internal } from "../_generated/api.js";
|
|
|
4
4
|
import { internalMutation, mutation } from "../_generated/server.js";
|
|
5
5
|
import { requireOrgId } from "../lib/auth.js";
|
|
6
6
|
// testFixtures/delegationDemoWorkflow — TEST-ONLY reference PARENT-side
|
|
7
|
-
// recipient for delegation
|
|
8
|
-
// convex/engine/delegationDemoWorkflow.ts. This is exactly the "bespoke
|
|
7
|
+
// recipient for delegation. This is exactly the "bespoke
|
|
9
8
|
// workflow" shape `engine/wakeup.ts`'s own comment describes ("any
|
|
10
9
|
// workflow -- a session, a durable job, or a bespoke one -- can be the wake
|
|
11
10
|
// target"): it parks on `step.awaitEvent` and, once
|
|
12
11
|
// `engine.wakeup.onWorkComplete` fires `sendEvent` (via
|
|
13
12
|
// `engine.delegation.delegateToSubagent` -> `engine.wakeup.enqueue`, the
|
|
14
|
-
//
|
|
13
|
+
// same public action this component ships), it patches the SAME `delegationRuns`
|
|
15
14
|
// row `delegateToSubagent` created -- proving A paused and was woken by
|
|
16
15
|
// B's completion, with zero polling.
|
|
17
16
|
export const workflow = new WorkflowManager(components.workflow);
|
|
@@ -4,8 +4,8 @@ import { components, internal } from "../_generated/api.js";
|
|
|
4
4
|
import { internalMutation, mutation } from "../_generated/server.js";
|
|
5
5
|
import { requireOrgId } from "../lib/auth.js";
|
|
6
6
|
// testFixtures/sandboxDemoWorkflow — TEST-ONLY reference recipient for the
|
|
7
|
-
//
|
|
8
|
-
//
|
|
7
|
+
// sandbox bridge, same shape/role as testFixtures/wakeupDemoWorkflow.ts.
|
|
8
|
+
// A real consumer's
|
|
9
9
|
// own workflow parks on `step.awaitEvent({ name: <awaitedEventName passed
|
|
10
10
|
// to engine/sandboxCallback.startRun> })` and does nothing else. Proves
|
|
11
11
|
// (component/sandboxCallback.componentPackaging.test.ts) the ONLY way this
|
|
@@ -4,7 +4,7 @@ import { components, internal } from "../_generated/api.js";
|
|
|
4
4
|
import { internalMutation, mutation } from "../_generated/server.js";
|
|
5
5
|
import { requireOrgId } from "../lib/auth.js";
|
|
6
6
|
// testFixtures/wakeupDemoWorkflow — TEST-ONLY reference recipient for the
|
|
7
|
-
// wake-up mechanism
|
|
7
|
+
// wake-up mechanism.
|
|
8
8
|
// A real consumer's own workflow does exactly this shape: call
|
|
9
9
|
// `step.awaitEvent({ name: <same name passed to engine/wakeup.enqueue> })`
|
|
10
10
|
// and do nothing else until it resolves. Proves (and is exercised by the
|
|
@@ -14,7 +14,7 @@ import { requireOrgId } from "../lib/auth.js";
|
|
|
14
14
|
// this file. Also exercises `engine/awaitEventTimeout` by accepting the
|
|
15
15
|
// blank `sandbox.timeout` event name as an alternate wake source.
|
|
16
16
|
//
|
|
17
|
-
// Versioned workflow discipline (workflow#35
|
|
17
|
+
// Versioned workflow discipline (workflow#35): ship
|
|
18
18
|
// `...V2` rather than editing `wakeupDemoWorkflowV1` in place once
|
|
19
19
|
// referenced by live work (not a live concern for a test fixture, kept for
|
|
20
20
|
// parity with the app-level source it was ported from).
|
package/package.json
CHANGED
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vantageos/agent-engine",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.8",
|
|
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
|
-
"license": "
|
|
6
|
+
"license": "FSL-1.1-Apache-2.0",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"convex",
|
|
9
|
+
"convex-component",
|
|
10
|
+
"agents",
|
|
11
|
+
"durable-agents",
|
|
12
|
+
"ai-agents",
|
|
13
|
+
"workflow",
|
|
14
|
+
"vantageos"
|
|
15
|
+
],
|
|
7
16
|
"publishConfig": {
|
|
8
17
|
"access": "public",
|
|
9
18
|
"tag": "alpha"
|
|
10
19
|
},
|
|
11
20
|
"files": [
|
|
12
21
|
"dist",
|
|
13
|
-
"README.md"
|
|
22
|
+
"README.md",
|
|
23
|
+
"LICENSE"
|
|
14
24
|
],
|
|
15
25
|
"exports": {
|
|
16
26
|
"./package.json": "./package.json",
|
|
@@ -32,9 +42,10 @@
|
|
|
32
42
|
"test:watch": "vitest",
|
|
33
43
|
"typecheck": "tsc --noEmit",
|
|
34
44
|
"build": "tsc -p tsconfig.build.json",
|
|
35
|
-
"prepublishOnly": "npm run build",
|
|
45
|
+
"prepublishOnly": "npm run build && npm run check:public",
|
|
36
46
|
"check:generated": "node scripts/check-generated-freshness.mjs",
|
|
37
|
-
"check:generated:content": "node scripts/check-generated-content.mjs"
|
|
47
|
+
"check:generated:content": "node scripts/check-generated-content.mjs",
|
|
48
|
+
"check:public": "node scripts/check-public-package.mjs"
|
|
38
49
|
},
|
|
39
50
|
"dependencies": {
|
|
40
51
|
"@convex-dev/agent": "0.6.4",
|