@vantageos/agent-engine 0.1.0-alpha.7 → 0.3.0-alpha.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.
Files changed (62) hide show
  1. package/README.md +153 -50
  2. package/dist/component/_generated/api.d.ts +14 -27
  3. package/dist/component/_generated/api.js +0 -25
  4. package/dist/component/_generated/component.d.ts +369 -92
  5. package/dist/component/_generated/component.js +0 -9
  6. package/dist/component/_generated/dataModel.d.ts +0 -38
  7. package/dist/component/_generated/dataModel.js +0 -9
  8. package/dist/component/_generated/server.d.ts +0 -106
  9. package/dist/component/_generated/server.js +0 -69
  10. package/dist/component/convex.config.js +0 -44
  11. package/dist/component/engine/agents.js +0 -7
  12. package/dist/component/engine/awaitEventTimeout.d.ts +1 -1
  13. package/dist/component/engine/awaitEventTimeout.js +18 -26
  14. package/dist/component/engine/connections.d.ts +74 -0
  15. package/dist/component/engine/connections.js +254 -0
  16. package/dist/component/engine/delegation.d.ts +1 -1
  17. package/dist/component/engine/delegation.js +0 -74
  18. package/dist/component/engine/directory.js +0 -18
  19. package/dist/component/engine/durableJob.d.ts +34 -4
  20. package/dist/component/engine/durableJob.js +333 -86
  21. package/dist/component/engine/mandates.js +0 -59
  22. package/dist/component/engine/queue.d.ts +97 -0
  23. package/dist/component/engine/queue.js +201 -0
  24. package/dist/component/engine/resolvers.d.ts +1 -1
  25. package/dist/component/engine/resolvers.js +6 -18
  26. package/dist/component/engine/sandboxCallback.d.ts +1 -1
  27. package/dist/component/engine/sandboxCallback.js +2 -79
  28. package/dist/component/engine/sandboxConfigProvider.d.ts +9 -0
  29. package/dist/component/engine/sandboxConfigProvider.js +32 -0
  30. package/dist/component/engine/sessions.d.ts +28 -10
  31. package/dist/component/engine/sessions.js +153 -165
  32. package/dist/component/engine/streams.d.ts +47 -0
  33. package/dist/component/engine/streams.js +162 -0
  34. package/dist/component/engine/toolApprovals.d.ts +1 -1
  35. package/dist/component/engine/toolApprovals.js +12 -37
  36. package/dist/component/engine/vpConnection.js +0 -40
  37. package/dist/component/engine/wakeup.d.ts +5 -7
  38. package/dist/component/engine/wakeup.js +54 -127
  39. package/dist/component/engine/workflows.d.ts +42 -0
  40. package/dist/component/engine/workflows.js +100 -41
  41. package/dist/component/engine/world.d.ts +249 -0
  42. package/dist/component/engine/world.js +665 -0
  43. package/dist/component/lib/auth.js +0 -26
  44. package/dist/component/lib/connectionSecret.d.ts +5 -0
  45. package/dist/component/lib/connectionSecret.js +32 -0
  46. package/dist/component/schema.d.ts +227 -77
  47. package/dist/component/schema.js +137 -250
  48. package/package.json +17 -3
  49. package/dist/component/engine/habits.d.ts +0 -70
  50. package/dist/component/engine/habits.js +0 -218
  51. package/dist/component/testFixtures/callerSteps.d.ts +0 -20
  52. package/dist/component/testFixtures/callerSteps.js +0 -90
  53. package/dist/component/testFixtures/delegationDemoWorkflow.d.ts +0 -18
  54. package/dist/component/testFixtures/delegationDemoWorkflow.js +0 -75
  55. package/dist/component/testFixtures/sandboxDemoWorkflow.d.ts +0 -19
  56. package/dist/component/testFixtures/sandboxDemoWorkflow.js +0 -69
  57. package/dist/component/testFixtures/vpTool.d.ts +0 -4
  58. package/dist/component/testFixtures/vpTool.js +0 -25
  59. package/dist/component/testFixtures/wakeupDemoWorkflow.d.ts +0 -19
  60. package/dist/component/testFixtures/wakeupDemoWorkflow.js +0 -77
  61. package/dist/component/testFixtures/wakeupWork.d.ts +0 -8
  62. package/dist/component/testFixtures/wakeupWork.js +0 -21
@@ -1,21 +1,8 @@
1
- import { WorkflowManager } from "@convex-dev/workflow";
1
+ import { WorkflowManager, vResultValidator, vWorkflowId } from "@convex-dev/workflow";
2
2
  import { v } from "convex/values";
3
3
  import { components, internal } from "../_generated/api.js";
4
- import { internalMutation, internalQuery } from "../_generated/server.js";
5
- // The durable, VERSIONED session workflow. This is what makes
6
- // `sessions.start` open a session PILOTED by `@convex-dev/workflow` rather
7
- // than a bare event table.
8
- //
9
- // Trust model at this boundary: the workflow engine runs with NO end-user
10
- // identity and NO client-supplied orgId (component isolation, same
11
- // discipline as component/engine/durableJob.ts and component/lib/auth.ts).
12
- // Every internal step below reads orgId from the `sessions` row itself --
13
- // never from an argument a workflow step could be handed by a caller.
14
- // Internal (server-to-server only) variants of the resolver/session
15
- // mutations, used by the workflow step handlers below. The workflow engine
16
- // runs with no end-user identity, so these read/write scoped strictly by
17
- // the orgId already recorded on the session row -- never trusting a
18
- // client-supplied orgId.
4
+ import { internalAction, internalMutation, internalQuery } from "../_generated/server.js";
5
+ import { agentIdOfRun, loadRun } from "./world.js";
19
6
  export const resolveManifestInternal = internalQuery({
20
7
  args: { sessionId: v.id("sessions") },
21
8
  returns: v.null(),
@@ -27,9 +14,6 @@ export const resolveManifestInternal = internalQuery({
27
14
  if (!agent || agent.orgId !== session.orgId) {
28
15
  throw new Error("Agent not found");
29
16
  }
30
- // Resolution result is consumed by the caller via the public
31
- // engine/resolvers:resolveManifest query; this internal step exists to
32
- // prove (and test) that the reread happens at each boundary.
33
17
  return null;
34
18
  },
35
19
  });
@@ -40,39 +24,17 @@ export const recordTurnStartedInternal = internalMutation({
40
24
  const session = await ctx.db.get(args.sessionId);
41
25
  if (!session)
42
26
  throw new Error("Session not found");
43
- await ctx.db.insert("sessionEvents", {
44
- orgId: session.orgId,
45
- sessionId: args.sessionId,
46
- name: "turn.started",
47
- payload: undefined,
48
- createdAt: Date.now(),
49
- });
50
27
  return null;
51
28
  },
52
29
  });
53
- // Versioned workflow discipline (workflow#35): "if you change much
54
- // of anything in a workflow while there are ongoing workflows, they'll
55
- // fail." We never edit a workflow function in place once sessions
56
- // reference it -- a breaking change ships as `sessionWorkflowV2`, and the
57
- // deploy is preceded by draining v1 sessions (0 rows with
58
- // sessions.workflowVersion == "v1" and status == "running"). Same
59
- // discipline as `engine/durableJob.ts:durableJobWorkflowV1`.
60
30
  export const workflow = new WorkflowManager(components.workflow);
61
- // sessionWorkflowV1 -- the durable session loop. At `session.started` and
62
- // at every `turn.started` boundary it rereads the agent aggregate (never
63
- // cached, never compiled) via `resolveManifestInternal`. Tool approvals
64
- // pause the workflow via `step.awaitEvent`, guarded by the self-built
65
- // timeout (workflow#177) once that surface is ported into this component.
66
31
  export const sessionWorkflowV1 = workflow.define({
67
32
  args: { sessionId: v.id("sessions") },
68
33
  returns: v.null(),
69
34
  handler: async (step, args) => {
70
- // session.started boundary: read the aggregate once at start.
71
35
  await step.runQuery(internal.engine.workflows.resolveManifestInternal, {
72
36
  sessionId: args.sessionId,
73
37
  });
74
- // turn.started boundary: re-read on every turn so an agent/skill edit
75
- // made mid-session is visible at the very next turn, with zero deploy.
76
38
  await step.runMutation(internal.engine.workflows.recordTurnStartedInternal, {
77
39
  sessionId: args.sessionId,
78
40
  });
@@ -82,3 +44,100 @@ export const sessionWorkflowV1 = workflow.define({
82
44
  return null;
83
45
  },
84
46
  });
47
+ export const resolveManifestInternalV2 = internalQuery({
48
+ args: { orgId: v.string(), runId: v.string() },
49
+ returns: v.null(),
50
+ handler: async (ctx, args) => {
51
+ const run = await loadRun(ctx, args.orgId, args.runId, "sessions", "Session not found");
52
+ const agent = await ctx.db.get(agentIdOfRun(ctx, run));
53
+ if (!agent || agent.orgId !== args.orgId) {
54
+ throw new Error("Agent not found");
55
+ }
56
+ return null;
57
+ },
58
+ });
59
+ export const sessionWorkflowV2 = workflow.define({
60
+ args: { orgId: v.string(), runId: v.string() },
61
+ returns: v.null(),
62
+ handler: async (step, args) => {
63
+ await step.runQuery(internal.engine.workflows.resolveManifestInternalV2, {
64
+ orgId: args.orgId,
65
+ runId: args.runId,
66
+ });
67
+ return null;
68
+ },
69
+ });
70
+ export const onSessionWorkflowComplete = internalMutation({
71
+ args: {
72
+ workflowId: vWorkflowId,
73
+ context: v.object({ sessionId: v.id("sessions") }),
74
+ result: vResultValidator,
75
+ },
76
+ returns: v.null(),
77
+ handler: async (ctx, args) => {
78
+ const session = await ctx.db.get(args.context.sessionId);
79
+ if (!session)
80
+ return null;
81
+ const sandboxConfigRow = await ctx.db
82
+ .query("sandboxConfig")
83
+ .withIndex("by_org_agent", (q) => q.eq("orgId", session.orgId).eq("agentId", session.agentId))
84
+ .unique();
85
+ const boxId = sandboxConfigRow?.boxId;
86
+ if (!boxId)
87
+ return null;
88
+ await ctx.scheduler.runAfter(0, internal.engine.workflows.stopBoxInternal, {
89
+ boxId,
90
+ });
91
+ return null;
92
+ },
93
+ });
94
+ export const onSessionWorkflowCompleteV2 = internalMutation({
95
+ args: {
96
+ workflowId: vWorkflowId,
97
+ context: v.object({ orgId: v.string(), runId: v.string() }),
98
+ result: vResultValidator,
99
+ },
100
+ returns: v.null(),
101
+ handler: async (ctx, args) => {
102
+ const { orgId, runId } = args.context;
103
+ let agentId;
104
+ try {
105
+ const run = await loadRun(ctx, orgId, runId, "sessions", "Session not found");
106
+ agentId = agentIdOfRun(ctx, run);
107
+ }
108
+ catch {
109
+ return null;
110
+ }
111
+ const sandboxConfigRow = await ctx.db
112
+ .query("sandboxConfig")
113
+ .withIndex("by_org_agent", (q) => q.eq("orgId", orgId).eq("agentId", agentId))
114
+ .unique();
115
+ const boxId = sandboxConfigRow?.boxId;
116
+ if (!boxId)
117
+ return null;
118
+ await ctx.scheduler.runAfter(0, internal.engine.workflows.stopBoxInternal, {
119
+ boxId,
120
+ });
121
+ return null;
122
+ },
123
+ });
124
+ export const stopBoxInternal = internalAction({
125
+ args: { boxId: v.string() },
126
+ returns: v.null(),
127
+ handler: async (_ctx, args) => {
128
+ const apiKey = process.env.BOAT_API_KEY;
129
+ if (!apiKey || apiKey.length === 0) {
130
+ throw new Error("stopBoxInternal: BOAT_API_KEY is not set; refusing to skip the box-stop call silently");
131
+ }
132
+ const baseUrl = process.env.BOX_API_BASE_URL ?? "https://ascii.dev/api/box/v1";
133
+ const response = await fetch(`${baseUrl.replace(/\/$/, "")}/boxes/${encodeURIComponent(args.boxId)}/stop`, {
134
+ method: "POST",
135
+ headers: { Authorization: `Bearer ${apiKey}` },
136
+ });
137
+ if (!response.ok) {
138
+ const text = await response.text();
139
+ throw new Error(`stopBoxInternal: POST /boxes/${args.boxId}/stop failed (${response.status}): ${text}`);
140
+ }
141
+ return null;
142
+ },
143
+ });
@@ -0,0 +1,249 @@
1
+ import { type DatabaseReader, type MutationCtx } from "../_generated/server.js";
2
+ import type { Doc, Id } from "../_generated/dataModel.js";
3
+ declare function slotToEventId(seq: number): string;
4
+ export type AppendEventArgs = {
5
+ orgId: string;
6
+ runId: string | null;
7
+ eventType: string;
8
+ stepId?: string;
9
+ hookId?: string;
10
+ correlationId?: string;
11
+ dataJson: string;
12
+ };
13
+ export declare function appendEventCore(ctx: MutationCtx, args: AppendEventArgs): Promise<{
14
+ event: {
15
+ eventId: string;
16
+ seq: number;
17
+ runId: string;
18
+ eventType: string;
19
+ stepId: string | undefined;
20
+ hookId: string | undefined;
21
+ correlationId: string | undefined;
22
+ dataJson: string;
23
+ createdAt: number;
24
+ };
25
+ run: {
26
+ runId: string;
27
+ status: "running" | "completed" | "cancelled" | "failed";
28
+ eventCount: number;
29
+ createdAt: number;
30
+ updatedAt: number;
31
+ };
32
+ step: {
33
+ runId: string;
34
+ stepId: string;
35
+ status: "running" | "completed" | "failed";
36
+ dataJson: string | undefined;
37
+ createdAt: number;
38
+ updatedAt: number;
39
+ } | null;
40
+ hook: {
41
+ runId: string;
42
+ hookId: string;
43
+ token: string;
44
+ status: "pending" | "disposed";
45
+ createdAt: number;
46
+ updatedAt: number;
47
+ } | null;
48
+ }>;
49
+ export declare const appendEvent: import("convex/server").RegisteredMutation<"public", {
50
+ stepId?: string | undefined;
51
+ hookId?: string | undefined;
52
+ correlationId?: string | undefined;
53
+ orgId: string;
54
+ runId: string | null;
55
+ dataJson: string;
56
+ eventType: string;
57
+ }, Promise<{
58
+ event: {
59
+ eventId: string;
60
+ seq: number;
61
+ runId: string;
62
+ eventType: string;
63
+ stepId: string | undefined;
64
+ hookId: string | undefined;
65
+ correlationId: string | undefined;
66
+ dataJson: string;
67
+ createdAt: number;
68
+ };
69
+ run: {
70
+ runId: string;
71
+ status: "running" | "completed" | "cancelled" | "failed";
72
+ eventCount: number;
73
+ createdAt: number;
74
+ updatedAt: number;
75
+ };
76
+ step: {
77
+ runId: string;
78
+ stepId: string;
79
+ status: "running" | "completed" | "failed";
80
+ dataJson: string | undefined;
81
+ createdAt: number;
82
+ updatedAt: number;
83
+ } | null;
84
+ hook: {
85
+ runId: string;
86
+ hookId: string;
87
+ token: string;
88
+ status: "pending" | "disposed";
89
+ createdAt: number;
90
+ updatedAt: number;
91
+ } | null;
92
+ }>>;
93
+ export declare function legacyCorrelationId(table: "sessions" | "durableJobs", legacyId: string): string;
94
+ export declare function findRunIdByCorrelation(ctx: MutationCtx, orgId: string, correlationId: string): Promise<string | null>;
95
+ export declare function openLegacyRun(ctx: MutationCtx, args: {
96
+ orgId: string;
97
+ table: "sessions" | "durableJobs";
98
+ legacyId: string;
99
+ data: Record<string, unknown>;
100
+ }): Promise<string>;
101
+ export declare function mirrorToRun(ctx: MutationCtx, args: {
102
+ orgId: string;
103
+ table: "sessions" | "durableJobs";
104
+ legacyId: string;
105
+ eventType: string;
106
+ stepId?: string;
107
+ dataJson?: string;
108
+ }): Promise<boolean>;
109
+ export type RunKind = "sessions" | "durableJobs";
110
+ export type RunStatus = "running" | "completed" | "failed" | "cancelled";
111
+ export type LoadedRun = {
112
+ runId: string;
113
+ status: RunStatus;
114
+ eventCount: number;
115
+ legacyId: string | null;
116
+ created: Record<string, unknown>;
117
+ };
118
+ export declare function loadRun(ctx: {
119
+ db: DatabaseReader;
120
+ }, orgId: string, runId: string, kind: RunKind, notFoundMessage: string): Promise<LoadedRun>;
121
+ export declare function legacySessionOf(ctx: {
122
+ db: DatabaseReader;
123
+ }, run: LoadedRun, orgId: string): Promise<Doc<"sessions"> | null>;
124
+ export declare function legacyJobOf(ctx: {
125
+ db: DatabaseReader;
126
+ }, run: LoadedRun, orgId: string): Promise<Doc<"durableJobs"> | null>;
127
+ export declare function agentIdOfRun(ctx: {
128
+ db: DatabaseReader;
129
+ }, run: LoadedRun): Id<"agents">;
130
+ export declare function payloadOrUndefined(dataJson: string): string | undefined;
131
+ export { slotToEventId };
132
+ export declare const getRun: import("convex/server").RegisteredQuery<"public", {
133
+ orgId: string;
134
+ runId: string;
135
+ }, Promise<{
136
+ runId: string;
137
+ status: "running" | "completed" | "cancelled" | "failed";
138
+ eventCount: number;
139
+ createdAt: number;
140
+ updatedAt: number;
141
+ } | null>>;
142
+ export declare const listRuns: import("convex/server").RegisteredQuery<"public", {
143
+ orgId: string;
144
+ }, Promise<{
145
+ runId: string;
146
+ status: "running" | "completed" | "cancelled" | "failed";
147
+ eventCount: number;
148
+ createdAt: number;
149
+ updatedAt: number;
150
+ }[]>>;
151
+ export declare const getStep: import("convex/server").RegisteredQuery<"public", {
152
+ orgId: string;
153
+ runId: string;
154
+ stepId: string;
155
+ }, Promise<{
156
+ runId: string;
157
+ stepId: string;
158
+ status: "running" | "completed" | "failed";
159
+ dataJson: string | undefined;
160
+ createdAt: number;
161
+ updatedAt: number;
162
+ } | null>>;
163
+ export declare const listSteps: import("convex/server").RegisteredQuery<"public", {
164
+ orgId: string;
165
+ runId: string;
166
+ }, Promise<{
167
+ runId: string;
168
+ stepId: string;
169
+ status: "running" | "completed" | "failed";
170
+ dataJson: string | undefined;
171
+ createdAt: number;
172
+ updatedAt: number;
173
+ }[]>>;
174
+ export declare const getEvent: import("convex/server").RegisteredQuery<"public", {
175
+ orgId: string;
176
+ runId: string;
177
+ eventId: string;
178
+ }, Promise<{
179
+ eventId: string;
180
+ seq: number;
181
+ runId: string;
182
+ eventType: string;
183
+ stepId: string | undefined;
184
+ hookId: string | undefined;
185
+ correlationId: string | undefined;
186
+ dataJson: string;
187
+ createdAt: number;
188
+ } | null>>;
189
+ export declare const listEvents: import("convex/server").RegisteredQuery<"public", {
190
+ orgId: string;
191
+ runId: string;
192
+ }, Promise<{
193
+ eventId: string;
194
+ seq: number;
195
+ runId: string;
196
+ eventType: string;
197
+ stepId: string | undefined;
198
+ hookId: string | undefined;
199
+ correlationId: string | undefined;
200
+ dataJson: string;
201
+ createdAt: number;
202
+ }[]>>;
203
+ export declare const listEventsByCorrelationId: import("convex/server").RegisteredQuery<"public", {
204
+ orgId: string;
205
+ correlationId: string;
206
+ }, Promise<{
207
+ eventId: string;
208
+ seq: number;
209
+ runId: string;
210
+ eventType: string;
211
+ stepId: string | undefined;
212
+ hookId: string | undefined;
213
+ correlationId: string | undefined;
214
+ dataJson: string;
215
+ createdAt: number;
216
+ }[]>>;
217
+ export declare const getHook: import("convex/server").RegisteredQuery<"public", {
218
+ orgId: string;
219
+ hookId: string;
220
+ }, Promise<{
221
+ runId: string;
222
+ hookId: string;
223
+ token: string;
224
+ status: "pending" | "disposed";
225
+ createdAt: number;
226
+ updatedAt: number;
227
+ } | null>>;
228
+ export declare const getHookByToken: import("convex/server").RegisteredQuery<"public", {
229
+ orgId: string;
230
+ token: string;
231
+ }, Promise<{
232
+ runId: string;
233
+ hookId: string;
234
+ token: string;
235
+ status: "pending" | "disposed";
236
+ createdAt: number;
237
+ updatedAt: number;
238
+ } | null>>;
239
+ export declare const listHooks: import("convex/server").RegisteredQuery<"public", {
240
+ orgId: string;
241
+ runId: string;
242
+ }, Promise<{
243
+ runId: string;
244
+ hookId: string;
245
+ token: string;
246
+ status: "pending" | "disposed";
247
+ createdAt: number;
248
+ updatedAt: number;
249
+ }[]>>;