anchor-ai-sdk 0.1.6 → 0.1.7
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 +337 -102
- package/dist/engine/background.d.ts +48 -0
- package/dist/engine/background.d.ts.map +1 -0
- package/dist/engine/background.js +98 -0
- package/dist/engine/background.js.map +1 -0
- package/dist/engine/dispatch.d.ts +54 -0
- package/dist/engine/dispatch.d.ts.map +1 -0
- package/dist/engine/dispatch.js +185 -0
- package/dist/engine/dispatch.js.map +1 -0
- package/dist/engine/events.d.ts +21 -1
- package/dist/engine/events.d.ts.map +1 -1
- package/dist/engine/guardrails.d.ts +54 -0
- package/dist/engine/guardrails.d.ts.map +1 -0
- package/dist/engine/guardrails.js +91 -0
- package/dist/engine/guardrails.js.map +1 -0
- package/dist/engine/inbox.d.ts +109 -0
- package/dist/engine/inbox.d.ts.map +1 -0
- package/dist/engine/inbox.js +94 -0
- package/dist/engine/inbox.js.map +1 -0
- package/dist/engine/loop.d.ts.map +1 -1
- package/dist/engine/loop.js +296 -241
- package/dist/engine/loop.js.map +1 -1
- package/dist/engine/types.d.ts +66 -6
- package/dist/engine/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/types.d.ts +7 -2
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/sandbox/docker/index.d.ts +8 -0
- package/dist/sandbox/docker/index.d.ts.map +1 -1
- package/dist/sandbox/docker/index.js +34 -1
- package/dist/sandbox/docker/index.js.map +1 -1
- package/dist/sandbox/e2b/index.d.ts.map +1 -1
- package/dist/sandbox/e2b/index.js +3 -0
- package/dist/sandbox/e2b/index.js.map +1 -1
- package/dist/sandbox/heyo/index.d.ts.map +1 -1
- package/dist/sandbox/heyo/index.js +3 -0
- package/dist/sandbox/heyo/index.js.map +1 -1
- package/dist/sandbox/local/index.d.ts.map +1 -1
- package/dist/sandbox/local/index.js +3 -0
- package/dist/sandbox/local/index.js.map +1 -1
- package/dist/sandbox/types.d.ts +9 -0
- package/dist/sandbox/types.d.ts.map +1 -1
- package/dist/sandbox/types.js.map +1 -1
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +5 -13
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/types.d.ts +25 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +26 -1
- package/dist/tools/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,147 +1,382 @@
|
|
|
1
1
|
<p align="center">
|
|
2
2
|
<picture>
|
|
3
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/hrithikkoduri/anchor-ai-sdk/
|
|
4
|
-
<img src="https://raw.githubusercontent.com/hrithikkoduri/anchor-ai-sdk/
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/hrithikkoduri/anchor-ai-sdk/d4e34e41ccb6fbb83d4c54824dd3383b5e84adc4/assets/readme-hero-dark.svg" />
|
|
4
|
+
<img src="https://raw.githubusercontent.com/hrithikkoduri/anchor-ai-sdk/d4e34e41ccb6fbb83d4c54824dd3383b5e84adc4/assets/readme-hero.svg" alt="Anchor. Your agent. Your machine. One runtime to wire them together." width="1200" />
|
|
5
5
|
</picture>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
|
-
<
|
|
8
|
+
<p align="center">
|
|
9
|
+
<strong>A TypeScript agent harness SDK.</strong><br />
|
|
10
|
+
Define the behavior. Choose the machine. Let the shared runtime handle the turns.
|
|
11
|
+
</p>
|
|
9
12
|
|
|
10
13
|
<p align="center">
|
|
11
|
-
<
|
|
12
|
-
|
|
14
|
+
<a href="https://www.npmjs.com/package/anchor-ai-sdk"><img src="https://img.shields.io/npm/v/anchor-ai-sdk?style=flat-square&color=c2410c" alt="npm version" /></a>
|
|
15
|
+
<a href="https://github.com/hrithikkoduri/anchor-ai-sdk/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/hrithikkoduri/anchor-ai-sdk/ci.yml?style=flat-square&label=ci&color=111114" alt="CI status" /></a>
|
|
16
|
+
<a href="https://github.com/hrithikkoduri/anchor-ai-sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-111114?style=flat-square" alt="MIT license" /></a>
|
|
17
|
+
<img src="https://img.shields.io/badge/node-%E2%89%A520-111114?style=flat-square" alt="Node.js 20 or newer" />
|
|
13
18
|
</p>
|
|
14
19
|
|
|
15
20
|
<p align="center">
|
|
16
|
-
<a href="https://
|
|
17
|
-
<a href="
|
|
18
|
-
<a href="
|
|
19
|
-
<
|
|
21
|
+
<a href="https://anchor-sdk.dev/docs.html"><strong>Documentation</strong></a> ·
|
|
22
|
+
<a href="#quickstart">Quickstart</a> ·
|
|
23
|
+
<a href="#one-sandbox-interface">Sandboxes</a> ·
|
|
24
|
+
<a href="#make-the-agent-yours">Custom agents</a> ·
|
|
25
|
+
<a href="https://anchor-sdk.dev/benchmarks.html">Benchmarks</a>
|
|
20
26
|
</p>
|
|
21
27
|
|
|
22
28
|
---
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
reads success out of a confident sentence; what to gate on it is your
|
|
33
|
-
policy, not a hidden wall.
|
|
34
|
-
- **Durable by construction.** Conversation, workspace, and the agent's own
|
|
35
|
-
notes survive folds, restarts, and budget deaths; the SDK ships the
|
|
36
|
-
resumption primitives (thread store, checkpoints, phase pauses, revival
|
|
37
|
-
planning), so resuming is wiring, not research.
|
|
38
|
-
- **Sandbox-first.** The machine is part of the design, not an afterthought:
|
|
39
|
-
one provider contract, adapters accepted by an executable conformance
|
|
40
|
-
suite.
|
|
41
|
-
|
|
42
|
-
## Out of the box
|
|
43
|
-
|
|
44
|
-
| | |
|
|
30
|
+
Anchor runs the **model → tools → observations → model** loop around your agent.
|
|
31
|
+
It combines configurable guardrails, context compaction, continuation primitives,
|
|
32
|
+
and structured events with a sandbox layer that can also be used on its own.
|
|
33
|
+
|
|
34
|
+
**Your app keeps control of the model, prompts, tools, storage, credentials, and
|
|
35
|
+
release policy.** There is no requirement to turn an agent into a workflow graph.
|
|
36
|
+
|
|
37
|
+
| Build around | What Anchor supplies |
|
|
45
38
|
| --- | --- |
|
|
46
|
-
| **
|
|
47
|
-
| **
|
|
48
|
-
| **
|
|
49
|
-
| **
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
| **Traces you can replay** | One fanout: one sequence number, redaction applied before *every* sink; NDJSON file, database rows, and a live projector share the same ordering. |
|
|
53
|
-
| **Sandbox plugins** | One `SandboxProvider` contract: Heyo microVMs, Docker, local. Capabilities are promises; the conformance suite holds adapters to them. Store-backed sessions give adopt-and-fallback continuity for free. |
|
|
54
|
-
| **Typed handoffs** | `finish({ handoff })` is shaped by *your* JSON schema; the engine declares the parameter, carries the object, and never interprets it. |
|
|
55
|
-
| **Priced & windowed models** | `llmFromCatalog` reads live prices and the genuine context window from the provider catalog; budgets and compaction configure themselves correctly. |
|
|
56
|
-
|
|
57
|
-
## Ten lines to a working agent
|
|
39
|
+
| **Your agent** | Chat and coding bundles, or your own strategy and toolset. Phases label the approach; they are not permissions. |
|
|
40
|
+
| **Your machine** | One `SandboxProvider` / `Sandbox` surface for Heyo Computer, E2B, Docker, and local development. |
|
|
41
|
+
| **Longer tasks** | Conversation compaction, thread-store interfaces, working notes, checkpoints, and opt-in revival planning. |
|
|
42
|
+
| **Observable execution** | Streaming events, tool-result metadata, NDJSON/custom trace sinks, and replay helpers. |
|
|
43
|
+
|
|
44
|
+
## Quickstart
|
|
58
45
|
|
|
59
46
|
```bash
|
|
60
47
|
npm install anchor-ai-sdk
|
|
61
48
|
```
|
|
62
49
|
|
|
63
|
-
|
|
50
|
+
Save as `agent.mjs`. This is ordinary JavaScript with ES modules; `.js` also works
|
|
51
|
+
when your `package.json` contains `"type": "module"`.
|
|
52
|
+
|
|
53
|
+
```js
|
|
64
54
|
import { chatAgent, llmFromCatalog, runAgent } from "anchor-ai-sdk";
|
|
65
55
|
|
|
66
|
-
const { llm } = await llmFromCatalog({
|
|
56
|
+
const { llm, compaction } = await llmFromCatalog({
|
|
67
57
|
baseUrl: "https://openrouter.ai/api/v1",
|
|
68
|
-
apiKey: process.env.OPENROUTER_KEY
|
|
69
|
-
model: "z-ai/glm-5.3",
|
|
58
|
+
apiKey: process.env.OPENROUTER_KEY,
|
|
59
|
+
model: process.env.MODEL ?? "z-ai/glm-5.3",
|
|
70
60
|
});
|
|
71
61
|
|
|
72
62
|
const result = await runAgent(
|
|
73
|
-
{ task: "Explain
|
|
74
|
-
{ llm, agent: chatAgent },
|
|
63
|
+
{ task: "Explain exponential backoff in plain English" },
|
|
64
|
+
{ llm, compaction, agent: chatAgent },
|
|
75
65
|
);
|
|
66
|
+
|
|
76
67
|
console.log(result.summary);
|
|
77
68
|
```
|
|
78
69
|
|
|
79
|
-
|
|
70
|
+
```bash
|
|
71
|
+
export OPENROUTER_KEY="your-key"
|
|
72
|
+
node agent.mjs
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
No sandbox is needed for this chat example. Model calls may incur cost.
|
|
76
|
+
`llmFromCatalog` uses provider pricing and context-window metadata when available;
|
|
77
|
+
pass its returned `compaction` settings to the engine as shown. Catalog lookup is
|
|
78
|
+
best-effort; configure overrides and fallbacks for endpoints without this metadata.
|
|
79
|
+
|
|
80
|
+
## One sandbox interface
|
|
81
|
+
|
|
82
|
+
**Configure the provider once. Keep the agent-facing machine interface the same.**
|
|
83
|
+
The same layer works with the built-in coding tools, custom agents, or direct
|
|
84
|
+
`sandbox.exec()` calls without an agent.
|
|
85
|
+
|
|
86
|
+
| Provider | Import | Boot configuration |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| **Heyo Computer** | `anchor-ai-sdk/sandbox/heyo` | Image artifact/store on the provider; host-built image kinds are also supported. |
|
|
89
|
+
| **E2B** | `anchor-ai-sdk/sandbox/e2b` | A prepared template name or ID, **not** an arbitrary Docker image at create time. |
|
|
90
|
+
| **Docker** | `anchor-ai-sdk/sandbox/docker` | An explicit container image, Docker CLI, and running daemon. |
|
|
91
|
+
| **Local** | `anchor-ai-sdk/sandbox/local` | Host processes and a working directory. **No isolation; trusted dev/CI only.** |
|
|
92
|
+
|
|
93
|
+
Choose one of the configurations below. Each defines `provider`; the common
|
|
94
|
+
runner that follows uses the `llm` and `compaction` from the quickstart.
|
|
95
|
+
|
|
96
|
+
<details open>
|
|
97
|
+
<summary><strong>Heyo Computer: choose an image and machine size</strong></summary>
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npm install @heyocomputer/hws
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
import { heyo } from "anchor-ai-sdk/sandbox/heyo";
|
|
105
|
+
|
|
106
|
+
const provider = heyo({
|
|
107
|
+
token: requiredEnv("HEYO_TOKEN"),
|
|
108
|
+
server: requiredEnv("HEYO_SERVER"),
|
|
109
|
+
namespace: requiredEnv("HEYO_NAMESPACE"),
|
|
110
|
+
image: requiredEnv("HEYO_IMAGE"),
|
|
111
|
+
imageKind: "artifact",
|
|
112
|
+
imageStore: requiredEnv("HEYO_IMAGE_STORE"),
|
|
113
|
+
sizeClass: "small",
|
|
114
|
+
diskSizeGb: 10,
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Use an artifact/store you can access and a toolchain suitable for the task.
|
|
119
|
+
Heyo configures its image on the provider and rejects per-sandbox `image` and
|
|
120
|
+
`workspacePath` overrides. `requiredEnv` is defined in the shared runner below.
|
|
121
|
+
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
<details>
|
|
125
|
+
<summary><strong>E2B: choose a prepared template</strong></summary>
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npm install 'e2b@^2.56'
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
import { e2b } from "anchor-ai-sdk/sandbox/e2b";
|
|
133
|
+
|
|
134
|
+
const provider = e2b({
|
|
135
|
+
apiKey: requiredEnv("E2B_API_KEY"),
|
|
136
|
+
template: requiredEnv("E2B_TEMPLATE"),
|
|
137
|
+
timeoutMs: 60 * 60_000, // sandbox lifetime, not a command timeout
|
|
138
|
+
});
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Build a template with `bash`, `git`, coreutils (including `timeout`), and the
|
|
142
|
+
language tools your task needs. `spec.image` can override the template per run;
|
|
143
|
+
`workspacePath` points to a Git workspace already prepared inside it. Neither
|
|
144
|
+
option turns a Docker image name into an E2B template automatically.
|
|
145
|
+
|
|
146
|
+
</details>
|
|
80
147
|
|
|
81
|
-
|
|
82
|
-
|
|
148
|
+
<details>
|
|
149
|
+
<summary><strong>Docker: supply your container image</strong></summary>
|
|
150
|
+
|
|
151
|
+
```js
|
|
83
152
|
import { docker } from "anchor-ai-sdk/sandbox/docker";
|
|
84
153
|
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
154
|
+
const provider = docker({
|
|
155
|
+
image: requiredEnv("ANCHOR_DOCKER_IMAGE"),
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
The image must already contain the required tools; Anchor does not infer or
|
|
160
|
+
install your repository's dependencies. `spec.image` overrides the default.
|
|
161
|
+
Use `workspacePath` only when the image already contains the Git workspace.
|
|
162
|
+
|
|
163
|
+
</details>
|
|
164
|
+
|
|
165
|
+
### Pass the machine to an agent
|
|
166
|
+
|
|
167
|
+
Combine **one** provider configuration above with this runner and the model setup
|
|
168
|
+
from the quickstart. Merge imports when composing an existing application.
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
import { codingAgent } from "anchor-ai-sdk";
|
|
172
|
+
|
|
173
|
+
function requiredEnv(name) {
|
|
174
|
+
const value = process.env[name];
|
|
175
|
+
if (!value) throw new Error(`Set ${name} before running this example.`);
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const sandbox = provider.create({
|
|
180
|
+
repoUrl: requiredEnv("REPO_URL"),
|
|
181
|
+
ref: process.env.REPO_REF ?? "main",
|
|
88
182
|
});
|
|
89
|
-
|
|
183
|
+
|
|
90
184
|
try {
|
|
185
|
+
await sandbox.start();
|
|
91
186
|
const result = await runAgent(
|
|
92
|
-
{ task: "Run the tests and
|
|
93
|
-
{ llm, agent: codingAgent, sandbox },
|
|
187
|
+
{ task: "Run the tests and report the results" },
|
|
188
|
+
{ llm, compaction, agent: codingAgent, sandbox },
|
|
94
189
|
);
|
|
95
|
-
console.log(result.summary, result.
|
|
190
|
+
console.log(result.summary, result.reason, result.evidence);
|
|
96
191
|
} finally {
|
|
97
192
|
await sandbox.destroy();
|
|
98
193
|
}
|
|
99
194
|
```
|
|
100
195
|
|
|
101
|
-
|
|
102
|
-
|
|
196
|
+
Provider boot settings and optional capabilities differ. Retention needs a cleanup
|
|
197
|
+
policy; remote machines and model calls can cost money. Private HTTPS repositories
|
|
198
|
+
can use `spec.git.token`, a caller-supplied credential callback.
|
|
199
|
+
|
|
200
|
+
The latest Docker adapter also supports `spec.egress: "none"`: it disconnects
|
|
201
|
+
container networks after `start()` setup. Other adapters reject that setting.
|
|
202
|
+
This is not a claim that all providers offer equivalent isolation.
|
|
203
|
+
|
|
204
|
+
**[Configuration examples](https://anchor-sdk.dev/docs.html#machine)** ·
|
|
205
|
+
**[Provider contract and image guide](https://github.com/hrithikkoduri/anchor-ai-sdk/blob/main/src/sandbox/README.md)**
|
|
206
|
+
|
|
207
|
+
## Make the agent yours
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
Agent = name + strategy + tools
|
|
211
|
+
Strategy = system prompt + phases + optional context preparation
|
|
212
|
+
Tool = model-visible JSON Schema + your handler
|
|
213
|
+
runAgent = task + agent + model + optional sandbox + runtime settings
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Use `chatAgent` or `codingAgent`, compose a bundle, or pass `strategy` and `tools`
|
|
217
|
+
separately. A custom agent is not required to be a coding agent or use a machine.
|
|
218
|
+
|
|
219
|
+
<details>
|
|
220
|
+
<summary><strong>Example: a small policy assistant with its own tool</strong></summary>
|
|
221
|
+
|
|
222
|
+
This fragment uses `llm` and `compaction` from the quickstart. The policy is demo
|
|
223
|
+
data; a real service needs your authorization, validation, and output limits.
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
import { defineTool, requireString } from "anchor-ai-sdk";
|
|
227
|
+
|
|
228
|
+
const policies = new Map([
|
|
229
|
+
["refunds", "Refunds are available within 30 days with the original receipt."],
|
|
230
|
+
]);
|
|
231
|
+
|
|
232
|
+
const lookupPolicy = defineTool(
|
|
233
|
+
{
|
|
234
|
+
name: "lookup_policy",
|
|
235
|
+
description: "Look up a policy by topic.",
|
|
236
|
+
parameters: {
|
|
237
|
+
type: "object",
|
|
238
|
+
properties: { topic: { type: "string" } },
|
|
239
|
+
required: ["topic"],
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
async (input) => {
|
|
243
|
+
const policy = policies.get(requireString(input, "topic").trim().toLowerCase());
|
|
244
|
+
return { ok: policy !== undefined, content: policy ?? "No policy found." };
|
|
245
|
+
},
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
const policyAgent = {
|
|
249
|
+
name: "policy-assistant",
|
|
250
|
+
strategy: {
|
|
251
|
+
name: "policy",
|
|
252
|
+
phases: [{ id: "answer", goal: "Answer using the retrieved policy." }],
|
|
253
|
+
requiredTools: ["lookup_policy"],
|
|
254
|
+
systemPrompt: () =>
|
|
255
|
+
"Look up policy before making policy claims. Say when it is unknown.",
|
|
256
|
+
},
|
|
257
|
+
tools: [lookupPolicy],
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const answer = await runAgent(
|
|
261
|
+
{ task: "Can I get a refund after 20 days?" },
|
|
262
|
+
{ llm, compaction, agent: policyAgent },
|
|
263
|
+
);
|
|
264
|
+
console.log(answer.summary);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
The schema is declared to the model; `defineTool` does not perform full JSON
|
|
268
|
+
Schema validation. It catches thrown handler errors as failed tool results.
|
|
269
|
+
Validate inputs and enforce permissions in your implementation.
|
|
270
|
+
|
|
271
|
+
</details>
|
|
272
|
+
|
|
273
|
+
**[Tools and schemas](https://anchor-sdk.dev/docs.html#tools)** ·
|
|
274
|
+
**[Runnable SDK examples](https://github.com/hrithikkoduri/anchor-ai-sdk/tree/main/examples)**
|
|
275
|
+
|
|
276
|
+
## Configure the runtime, not another loop
|
|
277
|
+
|
|
278
|
+
| Capability | Your controls |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| **Budgets and correction** | Step/token/known-dollar budgets, repeated-call detection, silent-tool and visible-verbosity nudges, prose checkpoints, and per-call output requests. |
|
|
281
|
+
| **Context and memory** | Catalog-derived or explicit compaction, supplied thread stores, agent-authored notes, and best-effort output spill. |
|
|
282
|
+
| **Revival and resume** | Opt-in budget warnings, `request_revival`, `planRevival`, and `ThreadBudget`. Your app persists state and decides whether to fund or enqueue another run. |
|
|
283
|
+
| **Snapshots and lifecycle** | Git-backed or custom snapshot hooks, optional push, phase-boundary pauses, heartbeats, and cancellation. |
|
|
284
|
+
| **Streaming and traces** | Raw `onEvent` updates; sequenced, pattern-redacted `traceSinks`; NDJSON files, custom sinks, live projection, and replay. |
|
|
285
|
+
| **Execution evidence** | Tool names/status/metadata plus recorded test-command outcomes and optional post-run Git freshness checks. Your app defines verification and release gates. |
|
|
103
286
|
|
|
104
|
-
|
|
287
|
+
<details>
|
|
288
|
+
<summary><strong>Example: limits, nudges, compaction, and a recorded trace</strong></summary>
|
|
105
289
|
|
|
106
|
-
|
|
290
|
+
Runtime options for a model and started sandbox configured by your host:
|
|
291
|
+
|
|
292
|
+
```js
|
|
293
|
+
import { JsonlTrace } from "anchor-ai-sdk";
|
|
294
|
+
import { randomUUID } from "node:crypto";
|
|
295
|
+
|
|
296
|
+
const tracePath = "./traces/" + randomUUID() + ".ndjson";
|
|
297
|
+
|
|
298
|
+
const result = await runAgent({ task: "Investigate the failing test" }, {
|
|
299
|
+
llm, sandbox, agent: codingAgent,
|
|
300
|
+
budgets: { maxSteps: 60, maxUsd: 3 },
|
|
301
|
+
compaction: { maxEstimatedTokens: 60_000, keepRecentTokens: 15_000 },
|
|
302
|
+
guardrails: {
|
|
303
|
+
repeatedToolCallLimit: 3,
|
|
304
|
+
toolOnlyNudgeLimit: 8,
|
|
305
|
+
verboseTurnLimit: 8_000,
|
|
306
|
+
proseCheckpoint: true,
|
|
307
|
+
},
|
|
308
|
+
maxOutputTokens: 16_000,
|
|
309
|
+
traceSinks: [new JsonlTrace(tracePath)],
|
|
310
|
+
onEvent(event) {
|
|
311
|
+
if (event.type === "llm_text_delta") process.stdout.write(event.text);
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Run usage is checked between calls and can overshoot a budget. Output limits are
|
|
317
|
+
requested from the provider. Compaction is lossy summarization using estimated
|
|
318
|
+
token sizes; persistence and spill require working storage. Trace redaction is
|
|
319
|
+
pattern-based, not a guarantee that all secrets are removed; raw `onEvent` events
|
|
320
|
+
are not redacted. Use distinct trace files/IDs per run in your application.
|
|
321
|
+
|
|
322
|
+
</details>
|
|
323
|
+
|
|
324
|
+
**[Compaction](https://anchor-sdk.dev/docs.html#compaction)** ·
|
|
325
|
+
**[Course correction](https://anchor-sdk.dev/docs.html#correction)** ·
|
|
326
|
+
**[Revival and host-side resume](https://anchor-sdk.dev/docs.html#revival)** ·
|
|
327
|
+
**[Streaming and detailed traces](https://anchor-sdk.dev/docs.html#traces)**
|
|
328
|
+
|
|
329
|
+
> **A completed run is not a correctness certificate.** `run_tests` records a
|
|
330
|
+
> command outcome and, when available, a Git hash captured **after** the command.
|
|
331
|
+
> `latestEvidenceForTree` can compare it with the current tree, but does not prove
|
|
332
|
+
> an immutable tested snapshot, require a full suite, or inspect assertions.
|
|
333
|
+
|
|
334
|
+
## Test the machine contract
|
|
335
|
+
|
|
336
|
+
`runSandboxConformance(provider)` from `anchor-ai-sdk/testing` exercises the
|
|
337
|
+
public sandbox contract: command results, deadlines, environment handling, Git
|
|
338
|
+
checkpoints, retention/adoption, and declared optional capabilities.
|
|
339
|
+
|
|
340
|
+
The repository configures local and Docker conformance in CI. Heyo and E2B live
|
|
341
|
+
suites are opt-in and credential-gated; having a suite is not certification that
|
|
342
|
+
every account, image, or template has passed it. Custom providers can use the
|
|
343
|
+
same contract and tests without rewriting the agent engine.
|
|
344
|
+
|
|
345
|
+
**[Conformance setup](https://anchor-sdk.dev/docs.html#conformance)** ·
|
|
346
|
+
**[Test source](https://github.com/hrithikkoduri/anchor-ai-sdk/tree/main/tests)**
|
|
347
|
+
|
|
348
|
+
## Evaluated, with the limits visible
|
|
349
|
+
|
|
350
|
+
The completed **Parasail GLM 5.3 / SWE-bench Lite-10** records show:
|
|
351
|
+
|
|
352
|
+
| | Anchor | mini-swe-agent |
|
|
107
353
|
| --- | --- | --- |
|
|
108
|
-
|
|
|
109
|
-
|
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
## Status
|
|
139
|
-
|
|
140
|
-
**Early alpha (0.x).** The API will move before 1.0, so pin exact versions. The
|
|
141
|
-
[`DECISIONS.md`](https://github.com/hrithikkoduri/anchor-ai-sdk/blob/main/DECISIONS.md) is the engineering log: every API has a written
|
|
142
|
-
reason, and the reasons moved with the code when this repo was extracted from
|
|
143
|
-
its monorepo.
|
|
144
|
-
|
|
145
|
-
- Repo / issues: [github.com/hrithikkoduri/anchor-ai-sdk](https://github.com/hrithikkoduri/anchor-ai-sdk)
|
|
146
|
-
- Docs: [anchor-sdk.dev](https://anchor-sdk.dev) (coming)
|
|
147
|
-
- License: MIT
|
|
354
|
+
| **Resolved** | **9 / 10** | **9 / 10** |
|
|
355
|
+
| Remaining task | Sympy patch unresolved | Matplotlib patch extraction failed; empty patch |
|
|
356
|
+
| Recorded usage | 11,363,962 tokens; $4.3162 | Not reported; no cost ratio claimed |
|
|
357
|
+
| Published limits | 120 steps / 25M tokens | Its own 250-step / $3 loop |
|
|
358
|
+
|
|
359
|
+
Both records name `zai-org/GLM-5.3` on Parasail, temperature 0, seed 42, and
|
|
360
|
+
Docker-backed tasks. This is a selected ten-task sample with different budgets
|
|
361
|
+
and an extraction failure, not the full benchmark or a general superiority
|
|
362
|
+
claim. The older 7/10 OpenRouter cost comparison is separate historical context.
|
|
363
|
+
|
|
364
|
+
**[Benchmark explorer](https://anchor-sdk.dev/benchmarks.html)** ·
|
|
365
|
+
**[Anchor artifacts](https://github.com/hrithikkoduri/anchor-ai-sdk/tree/main/evals/benchmarks/swe-bench/results/glm53-parasail)** ·
|
|
366
|
+
**[Mini artifacts](https://github.com/hrithikkoduri/anchor-ai-sdk/tree/main/evals/benchmarks/swe-bench/results/glm53-mini)**
|
|
367
|
+
|
|
368
|
+
## Status and contributing
|
|
369
|
+
|
|
370
|
+
**Early alpha, 0.x.** Pin exact versions and test your integration. Provider and
|
|
371
|
+
runtime features are version-specific; the current source may be ahead of the
|
|
372
|
+
installed package. Daytona, agent teams, and consumer skill bundles remain
|
|
373
|
+
roadmap work in the reviewed source.
|
|
374
|
+
|
|
375
|
+
Questions, bug reports, and provider contributions are welcome. Keep mechanics in
|
|
376
|
+
the SDK and product policy in the consumer; provider changes should include
|
|
377
|
+
conformance coverage and an honest capability declaration.
|
|
378
|
+
|
|
379
|
+
**[Issues](https://github.com/hrithikkoduri/anchor-ai-sdk/issues)** ·
|
|
380
|
+
**[Roadmap](https://github.com/hrithikkoduri/anchor-ai-sdk/blob/main/ROADMAP.md)** ·
|
|
381
|
+
**[Engineering decisions](https://github.com/hrithikkoduri/anchor-ai-sdk/blob/main/DECISIONS.md)** ·
|
|
382
|
+
**[MIT license](https://github.com/hrithikkoduri/anchor-ai-sdk/blob/main/LICENSE)**
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background-job delivery — the engine's half.
|
|
3
|
+
*
|
|
4
|
+
* A provider with `pollJob` lets `bash` detach a long command: the tool returns
|
|
5
|
+
* immediately with a job id. From there the engine owns the result: it polls
|
|
6
|
+
* outstanding jobs at every turn boundary, injects a finished one as a
|
|
7
|
+
* runtime-only message (never persisted, never shown to the user), and — when
|
|
8
|
+
* the run is about to end — waits for what is left instead of dropping it.
|
|
9
|
+
*
|
|
10
|
+
* Nothing here is provider-specific: `pollJob` returning `undefined` means
|
|
11
|
+
* "still running", and a throw means the receipt is gone.
|
|
12
|
+
*/
|
|
13
|
+
import type { ExecResult, Sandbox } from "../sandbox/types.js";
|
|
14
|
+
import type { BackgroundJob } from "./types.js";
|
|
15
|
+
/** How long to sleep between polls while waiting for a run-ending job. */
|
|
16
|
+
export declare const BACKGROUND_POLL_MS = 500;
|
|
17
|
+
export interface FinishedJob {
|
|
18
|
+
job: BackgroundJob;
|
|
19
|
+
result: ExecResult;
|
|
20
|
+
}
|
|
21
|
+
export interface LostJob {
|
|
22
|
+
job: BackgroundJob;
|
|
23
|
+
error: string;
|
|
24
|
+
}
|
|
25
|
+
export interface PollOutcome {
|
|
26
|
+
finished: FinishedJob[];
|
|
27
|
+
running: BackgroundJob[];
|
|
28
|
+
lost: LostJob[];
|
|
29
|
+
}
|
|
30
|
+
/** One non-blocking round over every outstanding job. */
|
|
31
|
+
export declare function pollBackgroundJobs(sandbox: Sandbox | undefined, jobs: BackgroundJob[]): Promise<PollOutcome>;
|
|
32
|
+
/**
|
|
33
|
+
* Wait for the outstanding jobs, bounded by each job's own deadline + grace.
|
|
34
|
+
* Used only when a run is about to finish normally: ending the run while a
|
|
35
|
+
* job is still out there would silently lose its result.
|
|
36
|
+
*/
|
|
37
|
+
export declare function waitForBackgroundJobs(sandbox: Sandbox | undefined, jobs: BackgroundJob[], opts?: {
|
|
38
|
+
signal?: AbortSignal;
|
|
39
|
+
sleep?: (ms: number) => Promise<void>;
|
|
40
|
+
}): Promise<PollOutcome>;
|
|
41
|
+
/**
|
|
42
|
+
* The runtime message the model sees. The body goes through the SAME
|
|
43
|
+
* truncate-and-spill path as a normal tool result, so a long test log is
|
|
44
|
+
* bounded and the full text stays addressable in scratch.
|
|
45
|
+
*/
|
|
46
|
+
export declare function renderBackgroundResult(job: FinishedJob, sandbox: Sandbox | undefined): Promise<string>;
|
|
47
|
+
export declare function renderLostJob(job: LostJob): string;
|
|
48
|
+
//# sourceMappingURL=background.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../src/engine/background.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAG/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,0EAA0E;AAC1E,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAItC,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,aAAa,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,aAAa,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,IAAI,EAAE,OAAO,EAAE,CAAC;CACjB;AAED,yDAAyD;AACzD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,IAAI,EAAE,aAAa,EAAE,GACpB,OAAO,CAAC,WAAW,CAAC,CAyBtB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,IAAI,EAAE,aAAa,EAAE,EACrB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAO,GACzE,OAAO,CAAC,WAAW,CAAC,CAwCtB;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,OAAO,GAAG,SAAS,GAC3B,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAKlD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { formatExec } from "../tools/types.js";
|
|
2
|
+
import { spillOrTruncate } from "../tools/truncate.js";
|
|
3
|
+
/** How long to sleep between polls while waiting for a run-ending job. */
|
|
4
|
+
export const BACKGROUND_POLL_MS = 500;
|
|
5
|
+
/** Grace past the job's own deadline before we call the receipt lost. */
|
|
6
|
+
const DEADLINE_GRACE_MS = 30_000;
|
|
7
|
+
/** One non-blocking round over every outstanding job. */
|
|
8
|
+
export async function pollBackgroundJobs(sandbox, jobs) {
|
|
9
|
+
if (!sandbox?.pollJob || jobs.length === 0) {
|
|
10
|
+
return { finished: [], running: [...jobs], lost: [] };
|
|
11
|
+
}
|
|
12
|
+
const finished = [];
|
|
13
|
+
const running = [];
|
|
14
|
+
const lost = [];
|
|
15
|
+
for (const job of jobs) {
|
|
16
|
+
try {
|
|
17
|
+
const result = await sandbox.pollJob(job.jobId, {
|
|
18
|
+
startedAt: job.startedAt,
|
|
19
|
+
...(job.timeoutSecs !== undefined
|
|
20
|
+
? { timeoutSecs: job.timeoutSecs }
|
|
21
|
+
: {}),
|
|
22
|
+
});
|
|
23
|
+
if (result)
|
|
24
|
+
finished.push({ job, result });
|
|
25
|
+
else
|
|
26
|
+
running.push(job);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
lost.push({
|
|
30
|
+
job,
|
|
31
|
+
error: err instanceof Error ? err.message : String(err),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { finished, running, lost };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Wait for the outstanding jobs, bounded by each job's own deadline + grace.
|
|
39
|
+
* Used only when a run is about to finish normally: ending the run while a
|
|
40
|
+
* job is still out there would silently lose its result.
|
|
41
|
+
*/
|
|
42
|
+
export async function waitForBackgroundJobs(sandbox, jobs, opts = {}) {
|
|
43
|
+
// Without a poller there is nothing to wait on; end the run and report the
|
|
44
|
+
// jobs instead of sleeping until a deadline that can never be observed.
|
|
45
|
+
if (!sandbox?.pollJob || jobs.length === 0) {
|
|
46
|
+
return { finished: [], running: [...jobs], lost: [] };
|
|
47
|
+
}
|
|
48
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
49
|
+
const finished = [];
|
|
50
|
+
const lost = [];
|
|
51
|
+
let remaining = [...jobs];
|
|
52
|
+
while (remaining.length > 0) {
|
|
53
|
+
if (opts.signal?.aborted)
|
|
54
|
+
break;
|
|
55
|
+
const outcome = await pollBackgroundJobs(sandbox, remaining);
|
|
56
|
+
finished.push(...outcome.finished);
|
|
57
|
+
lost.push(...outcome.lost);
|
|
58
|
+
remaining = outcome.running;
|
|
59
|
+
if (remaining.length === 0)
|
|
60
|
+
break;
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
const expired = remaining.filter((job) => now >
|
|
63
|
+
job.startedAt + ((job.timeoutSecs ?? 3600) + 30) * 1000 +
|
|
64
|
+
DEADLINE_GRACE_MS);
|
|
65
|
+
for (const job of expired) {
|
|
66
|
+
lost.push({
|
|
67
|
+
job,
|
|
68
|
+
error: "no result before the job's deadline",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (expired.length > 0) {
|
|
72
|
+
remaining = remaining.filter((job) => !expired.includes(job));
|
|
73
|
+
if (remaining.length === 0)
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
await sleep(BACKGROUND_POLL_MS);
|
|
77
|
+
}
|
|
78
|
+
return { finished, running: remaining, lost };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The runtime message the model sees. The body goes through the SAME
|
|
82
|
+
* truncate-and-spill path as a normal tool result, so a long test log is
|
|
83
|
+
* bounded and the full text stays addressable in scratch.
|
|
84
|
+
*/
|
|
85
|
+
export async function renderBackgroundResult(job, sandbox) {
|
|
86
|
+
const { result } = job;
|
|
87
|
+
const label = job.job.command ? ` (${job.job.command})` : "";
|
|
88
|
+
const status = result.timedOut
|
|
89
|
+
? `timed out (exit ${result.exitCode})`
|
|
90
|
+
: `exit ${result.exitCode}`;
|
|
91
|
+
const body = await spillOrTruncate(formatExec(result, job.job.timeoutSecs ?? 120), { sandbox, label: `background ${job.job.tool}` });
|
|
92
|
+
return `[runtime] Background job ${job.job.jobId}${label} finished: ${status}.\n${body}`;
|
|
93
|
+
}
|
|
94
|
+
export function renderLostJob(job) {
|
|
95
|
+
return (`[runtime] Background job ${job.job.jobId} is no longer readable: ${job.error}. ` +
|
|
96
|
+
`Do not assume it completed; check the workspace or rerun it if the result matters.`);
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=background.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background.js","sourceRoot":"","sources":["../../src/engine/background.ts"],"names":[],"mappings":"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"}
|