[PR #496] [MERGED] feat(deepagents): implement functional skills for quickjs middleware #512

Closed
opened 2026-06-05 17:23:31 -04:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/langchain-ai/deepagentsjs/pull/496
Author: @colifran
Created: 4/29/2026
Status: Merged
Merged: 4/30/2026
Merged by: @colifran

Base: mainHead: colifran/functional-skills


📝 Commits (9)

  • 2e7b8b2 add module field to skill metadat interface
  • 6658df8 add logic to strip type syntax for module sources
  • 2232cc0 implement skill loading for quickjs
  • cfcf85c implement repl session module loader
  • 26b7a27 move async module promise rest to dispose
  • a334fc7 wire functional skills into quickjs middleware
  • da06d8a changeset
  • e4d9027 fix error message
  • 3df73a4 one wasm instance per session

📊 Changes

13 files changed (+1757 additions, -20 deletions)

View changed files

.changeset/eager-oranges-help.md (+6 -0)
📝 libs/deepagents/src/middleware/skills.test.ts (+321 -0)
📝 libs/deepagents/src/middleware/skills.ts (+92 -0)
📝 libs/providers/quickjs/src/index.ts (+14 -2)
📝 libs/providers/quickjs/src/middleware.ts (+56 -0)
📝 libs/providers/quickjs/src/session.test.ts (+191 -0)
📝 libs/providers/quickjs/src/session.ts (+246 -17)
libs/providers/quickjs/src/skills.test.ts (+331 -0)
libs/providers/quickjs/src/skills.ts (+263 -0)
📝 libs/providers/quickjs/src/transform.test.ts (+157 -1)
📝 libs/providers/quickjs/src/transform.ts (+44 -0)
📝 libs/providers/quickjs/src/types.ts (+28 -0)
📝 libs/providers/quickjs/src/utils.ts (+8 -0)

📄 Description

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/").

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.

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

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/langchain-ai/deepagentsjs/pull/496 **Author:** [@colifran](https://github.com/colifran) **Created:** 4/29/2026 **Status:** ✅ Merged **Merged:** 4/30/2026 **Merged by:** [@colifran](https://github.com/colifran) **Base:** `main` ← **Head:** `colifran/functional-skills` --- ### 📝 Commits (9) - [`2e7b8b2`](https://github.com/langchain-ai/deepagentsjs/commit/2e7b8b2395357af2fd40bf8bf42a25e899ac6e73) add module field to skill metadat interface - [`6658df8`](https://github.com/langchain-ai/deepagentsjs/commit/6658df842c75c82480391ff99d0e157154fc605d) add logic to strip type syntax for module sources - [`2232cc0`](https://github.com/langchain-ai/deepagentsjs/commit/2232cc040fe9fa60bf881612caa9149dc560e7c4) implement skill loading for quickjs - [`cfcf85c`](https://github.com/langchain-ai/deepagentsjs/commit/cfcf85c42823a85da082619915005db06f9434fe) implement repl session module loader - [`26b7a27`](https://github.com/langchain-ai/deepagentsjs/commit/26b7a274d1b9a6adbfc20c55878351ae242d42a3) move async module promise rest to dispose - [`a334fc7`](https://github.com/langchain-ai/deepagentsjs/commit/a334fc7b959e74896de58de89e661e3e95946312) wire functional skills into quickjs middleware - [`da06d8a`](https://github.com/langchain-ai/deepagentsjs/commit/da06d8ad6fa26f972e4c6ee0f629405859b42f00) changeset - [`e4d9027`](https://github.com/langchain-ai/deepagentsjs/commit/e4d90273333fd3cc57f867811fd316dca9e4be55) fix error message - [`3df73a4`](https://github.com/langchain-ai/deepagentsjs/commit/3df73a4e7e6020ca560dee2c60f010ea203e509c) one wasm instance per session ### 📊 Changes **13 files changed** (+1757 additions, -20 deletions) <details> <summary>View changed files</summary> ➕ `.changeset/eager-oranges-help.md` (+6 -0) 📝 `libs/deepagents/src/middleware/skills.test.ts` (+321 -0) 📝 `libs/deepagents/src/middleware/skills.ts` (+92 -0) 📝 `libs/providers/quickjs/src/index.ts` (+14 -2) 📝 `libs/providers/quickjs/src/middleware.ts` (+56 -0) 📝 `libs/providers/quickjs/src/session.test.ts` (+191 -0) 📝 `libs/providers/quickjs/src/session.ts` (+246 -17) ➕ `libs/providers/quickjs/src/skills.test.ts` (+331 -0) ➕ `libs/providers/quickjs/src/skills.ts` (+263 -0) 📝 `libs/providers/quickjs/src/transform.test.ts` (+157 -1) 📝 `libs/providers/quickjs/src/transform.ts` (+44 -0) 📝 `libs/providers/quickjs/src/types.ts` (+28 -0) 📝 `libs/providers/quickjs/src/utils.ts` (+8 -0) </details> ### 📄 Description ### 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 | --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-06-05 17:23:31 -04:00
yindo closed this issue 2026-06-05 17:23:31 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/deepagentsjs#512