- ArrayField.add(): drop dead '?? null' fallback — defaultForField is total
for required fields, and we force required:true on the seed clone. Inline
comment explains the two separate uses of field.items (seed vs. render).
- primitive-fields.test.tsx: cover BooleanField checked→unchecked transition.
- load() now rejects non-object / array / null values from the Memento
(protects against hand-edited workspaceState containing junk) and returns
undefined in those cases.
- JSDoc on the class documents the caller's path-normalization contract.
- Adds 4 tests: reset on a non-existent key (no-op), workspace-root scoping
so two roots don't collide, save overwrites (does not merge), and the new
load-rejects-scalar-junk defensive branch.
- human-in-the-loop: inline the body (8 lines) instead of the double-cast
alias. Self-contained and avoids the 'as unknown as Adapter<K>' gymnastics.
- invokeRender: add JSDoc explaining why the ADAPTERS[kind] as Adapter<K>
cast is runtime-sound despite being unsound at the type level.
- Tests: add coverage for render-tool (args → parameters rename, toolCallId),
human-in-the-loop (matches action shape, status-gated result), custom-messages,
activity-message, and the no-render no-op path (9 tests total).
- v1-params: omit description field when undefined (cleaner output object);
recursion on [] suffix now naturally handles nested arrays like string[][];
add test for both.
- json-schema: JSDoc on JSONSchemaNode documenting MVP scope (no $ref, tuple
items, allOf/anyOf/oneOf); add tests for integer type and array without items.
- normalize: treat empty-enum as unconstrained instead of rejecting every
string (prevents a required field with enum:[] getting stuck); add comments
on the shallow array/object match; add tests for array/object/raw-json
defaults and the empty-enum path.
When a field emits undefined (e.g. NumberField with an optional field cleared),
previously the merged payload would contain { count: undefined } which
downstream render callbacks would see as a present-but-null property.
Now the key is removed entirely, matching the runtime contract for
'optional field not provided'.
Also adds three tests: nested object change, array add, and the
undefined-drop behavior.
- Empty textarea no longer clobbers prior value with {}. Fields representing
arrays, strings, or null would previously be silently overwritten; now empty
input means 'no change' and clears any prior parse error.
- Adds aria-invalid={!!error} on the textarea.
- Adds two tests: empty-input path (no onChange, no alert) and error-recovery
path (alert disappears + onChange fires with the new valid JSON).
- Documents the mount-only local-state contract so future callers aren't
surprised that external value resets don't propagate.
- NumberField: emit undefined for empty / non-finite input instead of silently
coercing to 0, matching the value: number | undefined type. Widens onChange
to (v: number | undefined) => void. Adds a test for the empty-input path.
- All three fields: drop redundant aria-label (wrapping <label> + htmlFor/id
provides the accessible name; the aria-label was double-announcing in
screen readers).
- Set native required attribute on input/select/checkbox so assistive tech
exposes the constraint alongside the (optional) suffix.
Previously bundler.ts (catalog) and hook-bundler.ts duplicated ~80 lines of
rolldown + nodeResolveFallback wiring. Extracts the common shell into
extension/shared/iife-bundler.ts exposing bundleIife() and IifeBundleResult.
bundler.ts and hook-bundler.ts are now thin wrappers supplying their specific
iifeName, externals, globals, and skip prefixes. Catalog and hook bundler
tests still pass unchanged; type aliases (BundleResult, HookBundleResult)
preserved for call-site source compatibility.
- Replaces the separate loadGitignore() walk + per-file isIgnored() loop with a
single directory walk that inherits gitignore scopes from parent to child.
For a workspace with G gitignore files and F source files, cuts syscalls
from O(2*(F+G)) to O(F+G) and ignore-checks from O(F*G) to O(F*depth).
- Drops unused ScanWorkspaceOptions.roots and unused rootDir param.
- HARDCODED_EXCLUDES is now a case-insensitive Set.
## Summary
- Remove `@langchain/community` from `@copilotkit/sdk-js`
peerDependencies — it's declared as `^0.3.58` but never imported
anywhere in the package
- This was the only constraint blocking `@langchain/core@1.x` resolution
for consumers using the LangGraph JS starter
## Context
`@copilotkit/sdk-js` has zero imports from `@langchain/community`. The
`^0.3.58` peer dep forced npm to resolve `@langchain/community@0.3.x`,
which transitively pulled in `@getzep/zep-cloud` → `langchain@0.3.x`,
conflicting with `sdk-js`'s own `langchain@>=1.0.0` peer requirement.
Removing the unused peer dep eliminates this resolution conflict
entirely.
## Test plan
- [ ] `npm install` in a fresh project using `@copilotkit/sdk-js`
resolves without peer dep warnings for `@langchain/community`
- [ ] Existing LangGraph JS starter installs cleanly
- [ ] No runtime behavior change (nothing imported from the removed dep)
@copilotkit/sdk-js declares @langchain/community as a peer dependency
but never imports from it. The ^0.3.58 constraint was the only thing
blocking @langchain/core@1.x resolution for consumers. Remove it
entirely since it serves no purpose.
Tests the /debug-events SSE endpoint across Express, Hono, Node, and
Fetch Direct adapters. Verifies SSE response format, event flow through
the DebugEventBus, envelope structure (timestamp, agentId, threadId,
runId, event), full event sequence, HTTP method validation (405 for
POST), and NODE_ENV=production guard (404).
Key implementation detail: reader.cancel() must NOT be awaited on
tee'd ReadableStreams (created by response.clone() in the fetch
handler) because Node.js blocks until the other tee branch is also
consumed/cancelled.