SIGN IN SIGN UP

feat(deepagents): implement functional skills for quickjs middleware (#496)

### Summary

Adds functional skill modules to the QuickJS REPL. Skills can now ship
JS/TS entrypoints via a module: frontmatter key on SKILL.md, which the
model dynamically imports at eval time with await
import("@/skills/<name>").

When skillsBackend is passed to createQuickJSMiddleware, the middleware
reads skillsMetadata from the current task state before each eval, scans
the source for skill references, and pushes the metadata + backend into
the session. The session wires a QuickJS module loader that lazily
fetches skill files from the backend, strips TypeScript syntax, and
caches the result for the lifetime of the session. Skills that are
referenced but not available on the agent short-circuit with a clear
error before evaluation starts.

On the deepagents side, SkillMetadata gains an optional module field
(validated and normalized from frontmatter), and formatSkillsList now
advertises importable skills in the system prompt with an await
import(...) hint.

```ts
const backend = new FilesystemBackend({ rootDir: "/project", virtualMode: true });

const agent = createDeepAgent({
  model: "claude-sonnet-4-6",
  backend,
  skills: ["/skills/"],
  middleware: [
    createQuickJSMiddleware({ skillsBackend: backend }),
  ],
});
```

### Tests

- Unit tests cover module path validation, TS syntax stripping, skill
loading (single/multi-file, error cases, bundle size cap), skill
reference scanning, module loader resolution and caching, and system
prompt formatting
- Ran an E2E eval that exercised the full pipeline from SKILL.md parse
through dynamic import and function call in the REPL, with a LangSmith
trace

### Benchmarks

#### memory: console_log concurrent
- Total time: 15820ms

| name | hz | min | max | mean | p75 | p99 | p995 | p999 | rme | samples
|

|--------------------------|---------|--------|--------|--------|--------|--------|--------|--------|--------|---------|
| 1 concurrent sessions | 145.91 | 1.8263 | 27.7702| 6.8536 | 9.1753 |
21.1492| 25.0420| 27.7702| ±5.30% | 730 |
| 8 concurrent sessions | 39.1773 | 15.5854| 61.5015| 25.5250| 27.8461|
49.0536| 61.5015| 61.5015| ±3.58% | 196 |
| 32 concurrent sessions | 13.9753 | 48.5504| 110.40 | 71.5547| 76.6394|
110.40 | 110.40 | 110.40 | ±3.72% | 70 |

---

#### memory: ptc_tools concurrent
- Total time: 16755ms

| name | hz | min | max | mean | p75 | p99 | p995 | p999 | rme | samples
|

|--------------------------|---------|--------|--------|--------|--------|--------|--------|--------|--------|---------|
| 1 concurrent sessions | 86.9205 | 4.1809 | 32.1833| 11.5048| 15.3222|
25.2676| 28.2697| 32.1833| ±4.76% | 435 |
| 8 concurrent sessions | 21.8310 | 33.5598| 69.0041| 45.8065| 50.8740|
60.2001| 69.0041| 69.0041| ±2.77% | 110 |
| 32 concurrent sessions | 7.0269 | 137.88 | 148.90 | 142.31 | 144.05 |
148.90 | 148.90 | 148.90 | ±0.70% | 36 |

---

#### throughput: single thread many iterations
- Total time: 31656ms

| name | hz | min | max | mean | p75 | p99 | p995 | p999 | rme | samples
|

|-------------------------------------------|--------|--------|--------|--------|--------|--------|--------|--------|--------|---------|
| 200 sequential evals (ptc + console.log) | 3.5897 | 240.92 | 347.19 |
278.58 | 289.81 | 341.02 | 347.19 | 347.19 | ±1.44% | 108 |
C
Colin Francis committed
8fd575f06ca27cb0bef1a649aa34124a2c04ddd3
Parent: 48fd284
Committed by GitHub <noreply@github.com> on 4/30/2026, 8:13:40 PM