Commit af9eb7b
Audit remediation: tests, isolate hardening, framework fixes, error hygiene (#465)
* test(ai-code-mode-skills): add unit test coverage for skill library
The package had 13 source files with zero unit tests. Added 116 tests
across 9 files covering trust strategies, memory + file storage, skill
management tools (including name-validation boundaries for register_skill),
bindings, skills-to-tools execution with mocked isolate driver, type
generation, the system-prompt renderer, and skill selection with a
mocked chat adapter.
* feat(ai-isolate-cloudflare): support production deployments and harden tool-name handling
The Worker was documented, commented, and configured as if unsafe_eval
only worked in wrangler dev. Updated src/worker/index.ts, wrangler.toml,
and the README to describe the production path (Cloudflare accounts
with the unsafe_eval binding enabled), and pointed users to auth /
rate limiting as the real production gate.
Also added assertSafeToolName in wrap-code.ts to reject tool names that
would break out of the generated function identifier, e.g.
"foo'); process.exit(1); (function bar() {". Added tests covering
quotes, backticks, whitespace, semicolons, newlines, empty strings,
leading digits, and the valid identifier shapes.
Added a new escape-attempts.test.ts covering JSON.stringify escaping
of adversarial tool-result values and verifying the result lands in
a plain object-literal assignment (never a template literal).
* refactor(ai-ollama): extract tool-converter with test coverage
Tool handling was inlined inside the text adapter with raw type casts.
Extracted into src/tools/function-tool.ts + tool-converter.ts matching
the structure used by ai-openai, ai-anthropic, ai-grok, and ai-groq.
Re-exported as convertFunctionToolToAdapterFormat and
convertToolsToProviderFormat from the package index.
Added 29 unit tests covering the converter, client utilities
(createOllamaClient, getOllamaHostFromEnv, generateId, estimateTokens),
and the text adapter's streaming behaviour: RUN/TEXT_MESSAGE/tool-call
lifecycle events, id synthesis when Ollama omits a tool-call id, tool
forwarding to the SDK in provider format, and structured-output JSON
parsing with error wrapping.
The package previously had 73 source files and zero unit tests.
* fix(frameworks): propagate useChat callback changes after re-render
onResponse, onChunk, and onCustomEvent were captured by reference at
ChatClient creation time. When a parent component re-rendered with
fresh closures, the client kept calling the originals.
- ai-react / ai-preact: wrap the three callbacks the same way
onFinish/onError already were, reading from optionsRef.current at
call time.
- ai-vue / ai-solid: wrap the callbacks to read options.xxx at call
time. This also fixes a subtler bug where using client.updateOptions
to swap callbacks could not clear them (the "!== undefined" guard
silently skipped undefined values).
- ai-svelte: documented the capture-at-creation behaviour — Svelte's
createChat runs once per instance and there's no per-render hook, so
callbacks are frozen unless the caller mutates the options object or
calls client.updateOptions imperatively.
Added a React regression test that rerenders with a new onChunk and
verifies the new callback fires while the original does not.
* refactor(ai, ai-openai): narrow error handling and stop logging raw errors
The three catch blocks that convert thrown values into RUN_ERROR events
(stream-to-response.ts, activities/stream-generation-result.ts,
activities/generateVideo/index.ts) were using catch(error: any) and
dereferencing .message / .code without checks. Added a shared
toRunErrorPayload(error, fallback) helper under activities/ that accepts
Error instances, plain objects with message/code fields, or bare strings,
and funnels all three sites through it with a per-site fallback message.
Removed four console.error calls in the OpenAI text adapter's chatStream
that dumped the full error object to stdout. SDK errors can carry the
original request (including auth headers), so the library no longer logs
them; upstream callers should convert errors into structured events.
Added 8 unit tests for toRunErrorPayload including a leaked-properties
test confirming the helper does not expose extra fields.
* test(isolates): add sandbox escape-attempt tests for Node and QuickJS drivers
Covers the attack surface a malicious skill / code-mode snippet might
probe: process/require/fetch should be unavailable, prototype pollution
must not leak to the host or between contexts, synchronous CPU-spin
loops must be interrupted by the timeout (not hang), and Function-
constructor escape attempts must execute inside the isolate (never
returning a real host process object).
QuickJS also gets a test that globalThis mutations inside one context
do not bleed into a sibling context.
* ci: apply automated fixes
* fix: address PR review feedback
- ai-preact: forward onCustomEvent in useChat (changeset claimed the fix
covered preact but it was silently dropped before reaching ChatClient).
- ai-isolate-cloudflare: reject JS reserved keywords as tool names
(return, class, function, if, await, ...) so the wrapper fails fast
at generation time instead of with a cryptic SyntaxError at eval.
- ai/src/activities/error-payload: apply typeof string check to the
Error branch's code field, matching the plain-object branch.
Some SDKs attach numeric or Symbol codes to Error instances.
- ai-ollama text-adapter test: strengthen OLLAMA_HOST assertion by
tracking the mocked Ollama constructor args, so the test fails if
the env var is ignored.
- ai-ollama utils test: rename 'when OLLAMA_HOST is unset' to 'empty'
since the setup stubs an empty string.
- ai-code-mode-skills file-storage test: use vi.useFakeTimers() for
the createdAt/updatedAt round-trip instead of a 5ms real sleep.
* ci: apply automated fixes
* fix(ai, ai-ollama): merge-driven regressions from CR
Address CR findings after merging main:
- ai-ollama tests: inject testLogger (from resolveDebugOption(false))
into every adapter.chatStream and adapter.structuredOutput call —
main's #467 made `logger` required on TextOptions, the PR's new tests
were written against the pre-#467 contract and crashed at runtime on
`logger.errors`/`logger.request` dereference.
- generateVideo: narrow `error` via toRunErrorPayload before handing it
to logger.errors. Previously passed the raw error object through the
logger meta, which would surface SDK request state (headers, payloads)
to any user-supplied logger — defeating the hardening the PR applies
to the RUN_ERROR event.
- error-narrowing changeset: update wording to match actual code. The
OpenAI text adapter's chatStream still logs under the merge, but now
through the narrowed `{message, code}` payload rather than raw errors.
Changeset previously claimed "the library now re-throws without
logging", which didn't match shipped behavior.
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>1 parent 008f015 commit af9eb7b
44 files changed
Lines changed: 3050 additions & 94 deletions
File tree
- .changeset
- packages/typescript
- ai-code-mode-skills
- tests
- ai-isolate-cloudflare
- src/worker
- tests
- ai-isolate-node/tests
- ai-isolate-quickjs/tests
- ai-ollama
- src
- adapters
- tools
- tests
- ai-openai/src/adapters
- ai-preact/src
- ai-react
- src
- tests
- ai-solid/src
- ai-svelte/src
- ai-vue/src
- ai
- src
- activities
- generateVideo
- tests
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
Lines changed: 302 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 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 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
0 commit comments