@auvira.ai/sdk 0.2.9 → 0.3.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 (68) hide show
  1. package/README.md +16 -11
  2. package/dist/agent/Agent.d.ts +7 -1
  3. package/dist/agent/Agent.d.ts.map +1 -1
  4. package/dist/agent/Agent.js +19 -1
  5. package/dist/agent/Agent.js.map +1 -1
  6. package/dist/agent/AgentRegistry.d.ts +1 -1
  7. package/dist/agent/AgentRegistry.d.ts.map +1 -1
  8. package/dist/agent/AgentRegistry.js.map +1 -1
  9. package/dist/agent/ConversationStore.d.ts +2 -0
  10. package/dist/agent/ConversationStore.d.ts.map +1 -1
  11. package/dist/agent/ConversationStore.js +4 -0
  12. package/dist/agent/ConversationStore.js.map +1 -1
  13. package/dist/agent/resolveModelConfig.d.ts.map +1 -1
  14. package/dist/agent/resolveModelConfig.js +3 -1
  15. package/dist/agent/resolveModelConfig.js.map +1 -1
  16. package/dist/agent/types.d.ts +6 -0
  17. package/dist/agent/types.d.ts.map +1 -1
  18. package/dist/agent/types.js.map +1 -1
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +1 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/runner/abortPoller.d.ts +4 -0
  24. package/dist/runner/abortPoller.d.ts.map +1 -0
  25. package/dist/runner/abortPoller.js +22 -0
  26. package/dist/runner/abortPoller.js.map +1 -0
  27. package/dist/runner/buildJobResult.d.ts +25 -0
  28. package/dist/runner/buildJobResult.d.ts.map +1 -0
  29. package/dist/runner/buildJobResult.js +56 -0
  30. package/dist/runner/buildJobResult.js.map +1 -0
  31. package/dist/runner/constants.d.ts +16 -0
  32. package/dist/runner/constants.d.ts.map +1 -0
  33. package/dist/runner/constants.js +16 -0
  34. package/dist/runner/constants.js.map +1 -0
  35. package/dist/runner/index.d.ts +14 -0
  36. package/dist/runner/index.d.ts.map +1 -0
  37. package/dist/runner/index.js +10 -0
  38. package/dist/runner/index.js.map +1 -0
  39. package/dist/runner/jobTypes.d.ts +80 -0
  40. package/dist/runner/jobTypes.d.ts.map +1 -0
  41. package/dist/runner/jobTypes.js +2 -0
  42. package/dist/runner/jobTypes.js.map +1 -0
  43. package/dist/runner/mapStreamEvents.d.ts +16 -0
  44. package/dist/runner/mapStreamEvents.d.ts.map +1 -0
  45. package/dist/runner/mapStreamEvents.js +196 -0
  46. package/dist/runner/mapStreamEvents.js.map +1 -0
  47. package/dist/runner/ndjsonWriter.d.ts +6 -0
  48. package/dist/runner/ndjsonWriter.d.ts.map +1 -0
  49. package/dist/runner/ndjsonWriter.js +18 -0
  50. package/dist/runner/ndjsonWriter.js.map +1 -0
  51. package/dist/runner/resolveRunnerEnv.d.ts +10 -0
  52. package/dist/runner/resolveRunnerEnv.d.ts.map +1 -0
  53. package/dist/runner/resolveRunnerEnv.js +28 -0
  54. package/dist/runner/resolveRunnerEnv.js.map +1 -0
  55. package/dist/runner/run.d.ts +13 -0
  56. package/dist/runner/run.d.ts.map +1 -0
  57. package/dist/runner/run.js +114 -0
  58. package/dist/runner/run.js.map +1 -0
  59. package/dist/runner/sessionStore.d.ts +12 -0
  60. package/dist/runner/sessionStore.d.ts.map +1 -0
  61. package/dist/runner/sessionStore.js +56 -0
  62. package/dist/runner/sessionStore.js.map +1 -0
  63. package/dist/runner/validateJob.d.ts +7 -0
  64. package/dist/runner/validateJob.d.ts.map +1 -0
  65. package/dist/runner/validateJob.js +158 -0
  66. package/dist/runner/validateJob.js.map +1 -0
  67. package/docs/sandbox-runner.md +199 -0
  68. package/package.json +14 -3
@@ -0,0 +1,158 @@
1
+ export class SandboxJobValidationError extends Error {
2
+ constructor(message) {
3
+ super(message);
4
+ this.name = "SandboxJobValidationError";
5
+ }
6
+ }
7
+ function isRecord(value) {
8
+ return typeof value === "object" && value !== null && !Array.isArray(value);
9
+ }
10
+ function readString(value, field) {
11
+ if (typeof value !== "string" || !value.trim()) {
12
+ throw new SandboxJobValidationError(`${field} must be a non-empty string`);
13
+ }
14
+ return value.trim();
15
+ }
16
+ function validateModel(raw) {
17
+ if (!isRecord(raw)) {
18
+ throw new SandboxJobValidationError("model must be an object");
19
+ }
20
+ if ("apiKey" in raw && raw.apiKey !== undefined && raw.apiKey !== null) {
21
+ throw new SandboxJobValidationError("model.apiKey is not allowed in job.json — use environment variables");
22
+ }
23
+ const id = readString(raw.id, "model.id");
24
+ const model = { id };
25
+ if (raw.provider !== undefined) {
26
+ if (raw.provider !== "openhands" && raw.provider !== "custom") {
27
+ throw new SandboxJobValidationError('model.provider must be "openhands" or "custom"');
28
+ }
29
+ model.provider = raw.provider;
30
+ }
31
+ if (raw.baseURL !== undefined) {
32
+ model.baseURL = readString(raw.baseURL, "model.baseURL");
33
+ }
34
+ return model;
35
+ }
36
+ function validateImages(raw) {
37
+ if (raw === undefined) {
38
+ return undefined;
39
+ }
40
+ if (!Array.isArray(raw)) {
41
+ throw new SandboxJobValidationError("images must be an array");
42
+ }
43
+ return raw.map((item, index) => {
44
+ if (!isRecord(item)) {
45
+ throw new SandboxJobValidationError(`images[${index}] must be an object`);
46
+ }
47
+ return {
48
+ data: readString(item.data, `images[${index}].data`),
49
+ mimeType: readString(item.mimeType, `images[${index}].mimeType`),
50
+ };
51
+ });
52
+ }
53
+ function validateCompletion(raw) {
54
+ if (raw === undefined) {
55
+ return undefined;
56
+ }
57
+ if (!isRecord(raw)) {
58
+ throw new SandboxJobValidationError("completion must be an object");
59
+ }
60
+ if ("isComplete" in raw) {
61
+ throw new SandboxJobValidationError("completion.isComplete is not serializable — omit from job.json");
62
+ }
63
+ const completion = {};
64
+ if (raw.mode !== undefined) {
65
+ if (raw.mode !== "default" && raw.mode !== "multi_file_required") {
66
+ throw new SandboxJobValidationError('completion.mode must be "default" or "multi_file_required"');
67
+ }
68
+ completion.mode = raw.mode;
69
+ }
70
+ if (raw.requireWiringAfterStyle !== undefined) {
71
+ completion.requireWiringAfterStyle = Boolean(raw.requireWiringAfterStyle);
72
+ }
73
+ if (raw.auto !== undefined) {
74
+ completion.auto = Boolean(raw.auto);
75
+ }
76
+ if (raw.confidenceThreshold !== undefined) {
77
+ const threshold = Number(raw.confidenceThreshold);
78
+ if (!Number.isFinite(threshold)) {
79
+ throw new SandboxJobValidationError("completion.confidenceThreshold must be a number");
80
+ }
81
+ completion.confidenceThreshold = threshold;
82
+ }
83
+ if (raw.styleAssetPatterns !== undefined) {
84
+ if (!Array.isArray(raw.styleAssetPatterns)) {
85
+ throw new SandboxJobValidationError("completion.styleAssetPatterns must be an array");
86
+ }
87
+ completion.styleAssetPatterns = raw.styleAssetPatterns.map((p) => readString(p, "styleAssetPatterns[]"));
88
+ }
89
+ if (raw.wiringPatterns !== undefined) {
90
+ if (!Array.isArray(raw.wiringPatterns)) {
91
+ throw new SandboxJobValidationError("completion.wiringPatterns must be an array");
92
+ }
93
+ completion.wiringPatterns = raw.wiringPatterns.map((p) => readString(p, "wiringPatterns[]"));
94
+ }
95
+ if (raw.multiStep !== undefined) {
96
+ if (!isRecord(raw.multiStep)) {
97
+ throw new SandboxJobValidationError("completion.multiStep must be an object");
98
+ }
99
+ completion.multiStep = {};
100
+ for (const key of ["minToolCalls", "minModelTurns", "maxExtraTurnsAfterStyleOnly"]) {
101
+ if (raw.multiStep[key] !== undefined) {
102
+ const value = Number(raw.multiStep[key]);
103
+ if (!Number.isFinite(value)) {
104
+ throw new SandboxJobValidationError(`completion.multiStep.${key} must be a number`);
105
+ }
106
+ completion.multiStep[key] = value;
107
+ }
108
+ }
109
+ }
110
+ return completion;
111
+ }
112
+ /** Validates and parses raw job JSON into SandboxAuviraJobInput v1. */
113
+ export function validateSandboxJob(raw) {
114
+ if (!isRecord(raw)) {
115
+ throw new SandboxJobValidationError("job.json must be a JSON object");
116
+ }
117
+ if (raw.version !== 1) {
118
+ throw new SandboxJobValidationError("job.version must be 1");
119
+ }
120
+ if ("apiKey" in raw && raw.apiKey !== undefined) {
121
+ throw new SandboxJobValidationError("apiKey is not allowed in job.json");
122
+ }
123
+ const editJobId = readString(raw.editJobId, "editJobId");
124
+ const workspacePath = raw.workspacePath === undefined
125
+ ? "/vercel/sandbox"
126
+ : readString(raw.workspacePath, "workspacePath");
127
+ const promptText = readString(raw.promptText, "promptText");
128
+ const model = validateModel(raw.model);
129
+ const job = {
130
+ version: 1,
131
+ editJobId,
132
+ workspacePath,
133
+ promptText,
134
+ model,
135
+ images: validateImages(raw.images),
136
+ resumeAgentId: raw.resumeAgentId === undefined
137
+ ? undefined
138
+ : readString(raw.resumeAgentId, "resumeAgentId"),
139
+ selectedDom: isRecord(raw.selectedDom)
140
+ ? raw.selectedDom
141
+ : undefined,
142
+ completion: validateCompletion(raw.completion),
143
+ validation: isRecord(raw.validation)
144
+ ? {
145
+ skip: raw.validation.skip === undefined ? undefined : Boolean(raw.validation.skip),
146
+ command: raw.validation.command === undefined
147
+ ? undefined
148
+ : readString(raw.validation.command, "validation.command"),
149
+ timeoutMs: raw.validation.timeoutMs === undefined
150
+ ? undefined
151
+ : Number(raw.validation.timeoutMs),
152
+ }
153
+ : undefined,
154
+ reuseWorkspace: raw.reuseWorkspace === undefined ? undefined : Boolean(raw.reuseWorkspace),
155
+ };
156
+ return job;
157
+ }
158
+ //# sourceMappingURL=validateJob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validateJob.js","sourceRoot":"","sources":["../../src/runner/validateJob.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,199 @@
1
+ # Vercel Sandbox Runner
2
+
3
+ Run Auvira agent edits inside a Vercel Sandbox VM while the host Next.js API stays in serverless Lambda. This mirrors the Cursor in-VM runner pattern: the host writes a job file, spawns the runner inside the sandbox, and polls NDJSON progress.
4
+
5
+ ## Architecture
6
+
7
+ ```mermaid
8
+ sequenceDiagram
9
+ participant Host as Host_Lambda
10
+ participant VM as Sandbox_VM
11
+ participant Runner as auvira_sdk_run
12
+ participant Agent as Agent_in_place
13
+
14
+ Host->>VM: write job.json
15
+ Host->>VM: spawn auvira-sdk-run --job editJobId
16
+ Runner->>Agent: Agent.create cwd=/vercel/sandbox
17
+ Runner->>Agent: agent.send(job fields)
18
+ loop stream
19
+ Agent-->>Runner: AgentRunEvent
20
+ Runner-->>VM: append events.ndjson
21
+ end
22
+ Runner->>VM: result.json
23
+ Host->>VM: poll events.ndjson
24
+ ```
25
+
26
+ The SDK package does **not** call the Vercel Sandbox SDK. The host app (~150 lines) writes jobs and spawns the runner command.
27
+
28
+ ## Directory layout
29
+
30
+ Default jobs root: `/vercel/.auvira/auvira-jobs` (override with `AUVIRA_JOBS_ROOT`).
31
+
32
+ ```
33
+ {AUVIRA_JOBS_ROOT}/
34
+ {editJobId}/
35
+ job.json # input (no secrets)
36
+ events.ndjson # append-only progress + final result line
37
+ result.json # terminal outcome
38
+ abort.json # host writes to cancel (optional)
39
+ sessions/
40
+ {agentId}.json # conversation + vision state for resume
41
+ ```
42
+
43
+ ## Install and run
44
+
45
+ ```bash
46
+ npm install @auvira.ai/sdk
47
+ ```
48
+
49
+ Inside the sandbox VM:
50
+
51
+ ```bash
52
+ CUSTOM_MODEL_API_KEY=... \
53
+ CUSTOM_MODEL_JSON_MODE=1 \
54
+ node node_modules/@auvira.ai/sdk/dist/runner/run.js --job <editJobId>
55
+ ```
56
+
57
+ Or use the bin:
58
+
59
+ ```bash
60
+ auvira-sdk-run --job <editJobId>
61
+ ```
62
+
63
+ ## Environment variables
64
+
65
+ | Variable | Required | Description |
66
+ |----------|----------|-------------|
67
+ | `CUSTOM_MODEL_API_KEY` | Yes | Model API key (MiniMax, OpenRouter, etc.) |
68
+ | `CUSTOM_MODEL_BASE_URL` | No | Model base URL override |
69
+ | `CUSTOM_MODEL_ID` | No | Model id override (default `MiniMax-M3`) |
70
+ | `CUSTOM_MODEL_JSON_MODE` | Recommended | Set to `1` for JSON-mode harness |
71
+ | `AUVIRA_JOBS_ROOT` | No | Jobs directory (default `/vercel/.auvira/auvira-jobs`) |
72
+ | `AUVIRA_CURSOR_JOB_ID` | No | Job id if `--job` not passed |
73
+
74
+ `CUSTOM_MODEL_API_KEY` is read from the environment only — never from `job.json`.
75
+
76
+ ## Job input (`SandboxAuviraJobInput` v1)
77
+
78
+ ```json
79
+ {
80
+ "version": 1,
81
+ "editJobId": "abc123",
82
+ "workspacePath": "/vercel/sandbox",
83
+ "promptText": "CURSOR SYSTEM RULES\n\n---\n\nOWNER REQUEST:\nUpdate hero headline",
84
+ "images": [
85
+ { "data": "<base64>", "mimeType": "image/png" }
86
+ ],
87
+ "selectedDom": {
88
+ "sectionIndex": 6,
89
+ "sectionTitle": "Our Services",
90
+ "kind": "section"
91
+ },
92
+ "completion": {
93
+ "mode": "multi_file_required",
94
+ "requireWiringAfterStyle": true,
95
+ "auto": false
96
+ },
97
+ "validation": { "skip": true },
98
+ "reuseWorkspace": false,
99
+ "resumeAgentId": "optional-agent-uuid",
100
+ "model": {
101
+ "id": "openrouter/minimax/minimax-m3",
102
+ "provider": "custom",
103
+ "baseURL": "https://api.minimax.io/v1"
104
+ }
105
+ }
106
+ ```
107
+
108
+ - `promptText` must use harness format (`\n\n---\n\n` delimiter) for website edits.
109
+ - `images` are base64 only — no host filesystem paths.
110
+ - `completion.isComplete` is not allowed (not JSON-serializable).
111
+ - `model.apiKey` is rejected by the validator.
112
+
113
+ ## Result (`SandboxAuviraJobResult`)
114
+
115
+ Written to `result.json` and appended as the final `events.ndjson` line:
116
+
117
+ ```json
118
+ {
119
+ "ok": true,
120
+ "agentId": "uuid",
121
+ "sessionResumed": false,
122
+ "runId": "run-uuid",
123
+ "summary": "Applied 2 edit(s)",
124
+ "tokenUsage": { "inputTokens": 100, "outputTokens": 50 },
125
+ "nativeToolCallCount": 8,
126
+ "cursorReportedSuccess": true
127
+ }
128
+ ```
129
+
130
+ `changedFiles` are computed by the host (workspace hash before/after), not returned by the runner.
131
+
132
+ ## NDJSON protocol
133
+
134
+ Each line in `events.ndjson`:
135
+
136
+ ```json
137
+ {"type":"progress","event":{"type":"step","id":"cursor_session","label":"Auvira agent ready","status":"completed"}}
138
+ {"type":"progress","event":{"type":"activity_trace","entry":{"kind":"tool_start","toolName":"read"}}}
139
+ {"type":"result","result":{"ok":true,"cursorReportedSuccess":true}}
140
+ ```
141
+
142
+ Parse lines in the host with:
143
+
144
+ ```ts
145
+ import { parseSandboxAuviraRunnerLine } from "@auvira.ai/sdk";
146
+
147
+ const event = parseSandboxAuviraRunnerLine(line);
148
+ ```
149
+
150
+ ## Host spawn (pseudocode)
151
+
152
+ ```ts
153
+ import { join } from "node:path";
154
+
155
+ const jobsRoot = "/vercel/.auvira/auvira-jobs";
156
+ const editJobId = "edit-abc";
157
+ const jobDir = join(jobsRoot, editJobId);
158
+
159
+ await sandbox.fs.writeFile(join(jobDir, "job.json"), JSON.stringify(job));
160
+
161
+ await sandbox.runCommand({
162
+ cmd: "sh",
163
+ args: [
164
+ "-c",
165
+ `CUSTOM_MODEL_API_KEY='$KEY' CUSTOM_MODEL_JSON_MODE=1 node '${runnerPath}/run.js' --job '${editJobId}'`,
166
+ ],
167
+ cwd: "/vercel/.auvira/auvira-runner",
168
+ });
169
+
170
+ // Poll join(jobDir, "events.ndjson") for new lines; read result.json when done.
171
+ ```
172
+
173
+ ## Session resume
174
+
175
+ When `resumeAgentId` is set, the runner loads `{jobsRoot}/sessions/{agentId}.json` and restores conversation + vision images across VM spawns. After a successful run, the runner updates the session file.
176
+
177
+ ## Security
178
+
179
+ - Never put API keys, tokens, or secrets in `job.json`.
180
+ - Reference images must be base64 in the job payload.
181
+ - Stream output is secret-masked via the SDK event bus.
182
+
183
+ ## Package exports
184
+
185
+ ```ts
186
+ import { parseSandboxAuviraRunnerLine, mapAuviraStreamEventToProgress } from "@auvira.ai/sdk";
187
+ import type { SandboxAuviraJobInput, SandboxAuviraJobResult } from "@auvira.ai/sdk";
188
+ ```
189
+
190
+ Subpath: `@auvira.ai/sdk/runner` (types + CLI module).
191
+
192
+ ## Changelog
193
+
194
+ ### 0.3.0
195
+
196
+ - Added Vercel Sandbox runner CLI (`auvira-sdk-run`)
197
+ - Added `@auvira.ai/sdk/runner` export
198
+ - Added session-file resume (`agentId`, `initialConversation` on `Agent.create`)
199
+ - Added NDJSON progress protocol for host polling
package/package.json CHANGED
@@ -1,20 +1,28 @@
1
1
  {
2
2
  "name": "@auvira.ai/sdk",
3
- "version": "0.2.9",
3
+ "version": "0.3.0",
4
4
  "description": "Cursor-SDK-compatible visual coding agent with custom model support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "auvira-sdk-run": "./dist/runner/run.js"
10
+ },
8
11
  "exports": {
9
12
  ".": {
10
13
  "types": "./dist/index.d.ts",
11
14
  "import": "./dist/index.js"
15
+ },
16
+ "./runner": {
17
+ "types": "./dist/runner/index.d.ts",
18
+ "import": "./dist/runner/run.js"
12
19
  }
13
20
  },
14
21
  "files": [
15
22
  "dist",
16
23
  "README.md",
17
- "LICENSE"
24
+ "LICENSE",
25
+ "docs"
18
26
  ],
19
27
  "repository": {
20
28
  "type": "git",
@@ -33,7 +41,10 @@
33
41
  "test:unit": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__ --exclude 'src/__tests__/real/**' --exclude 'src/__tests__/flex/real-*.e2e.test.ts'",
34
42
  "test:flex": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__/flex",
35
43
  "test:flex:unit": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__/flex --exclude 'src/__tests__/flex/real-*.e2e.test.ts'",
36
- "test:real": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__/real src/__tests__/flex/real-*.e2e.test.ts"
44
+ "test:real": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__/real src/__tests__/flex/real-*.e2e.test.ts src/__tests__/runner/run-cli.real.e2e.test.ts",
45
+ "test:runner": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__/runner --exclude 'src/__tests__/runner/**/*.real.e2e.test.ts'",
46
+ "test:runner:real": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__/runner/run-cli.real.e2e.test.ts src/__tests__/runner/run-cli-vibe-consumer.real.e2e.test.ts",
47
+ "test:runner:vibe": "node --env-file=.env ./node_modules/vitest/vitest.mjs run src/__tests__/runner/run-cli-vibe-consumer.real.e2e.test.ts"
37
48
  },
38
49
  "keywords": [
39
50
  "agent",