Uh oh!
There was an error while loading. Please reload this page.
chore: version packages - #1287
Merged
Merged
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@objectstack/plugin-auth@6.2.0
Minor Changes
b4c74a9: WebContainer (StackBlitz) signup compatibility:
AuthManagernow auto-detectsWebContainer runtimes at construction time and swaps better-auth's default
node:crypto.scrypt-based password hasher for the pure-JS hasher from@better-auth/utils/password(which uses@noble/hashes/scryptunder thehood).
Why: WebContainer's
node:cryptopolyfill ships an incompletescryptimplementation that throws
TypeError: y.run is not a functionon everysignup, blocking template demos on StackBlitz. The pure-JS implementation is
byte-compatible with the Node hasher (same scrypt params, same
salt:keyHexstorage format), so accounts created under either hasher remain mutually
verifiable — no migration, no template changes.
Scope: detection short-circuits to
undefinedon real Node, so productiondeployments are completely unaffected — the JS fallback module is only
dynamically imported when one of
process.versions.webcontainer,SHELLcontainingjsh, orSTACKBLITZenv is present.Templates (
@template/todo,@template/contracts, …) require no changes;the fix lives entirely inside
@objectstack/plugin-auth.Patch Changes
@objectstack/service-ai@6.2.0
Minor Changes
b4c74a9: Actions-as-tools Phase 3 — Human-In-The-Loop approval queue.
Dangerous declarative actions (
confirmText,mode:'delete',variant:'danger') can now be exposed to the LLM safely. Instead of being skipped outright, they are registered as tools whose handler enqueues a pending request and returns{ status: 'pending_approval', pendingActionId }to the model. A human approves (or rejects) from Studio's pending-actions inbox; the service then re-runs the exact same dispatcher.New surface
ai_pending_actions(id, conversation_id?, message_id?, object_name, action_name, tool_name, tool_input, status [pending|approved|executed|failed|rejected], result?, error?, rejection_reason?, proposed_by, decided_by?, proposed_at, decided_at?).AiPendingActionViewwithpending/executed/rejected/failedsub-views and per-row Approve / Reject API actions.IAIService(all optional, gated on a wiredIDataEngine):proposePendingAction(input) → { id }approvePendingAction(id, actorId) → { status, result?, error? }rejectPendingAction(id, actorId, reason?)listPendingActions(filter?) → PendingActionRow[]PendingActionStatus,ProposePendingActionInput,PendingActionRow.GET /api/v1/ai/pending-actions(ai:read)GET /api/v1/ai/pending-actions/:id(ai:read)POST /api/v1/ai/pending-actions/:id/approve(ai:approve)POST /api/v1/ai/pending-actions/:id/reject(ai:approve)actionRequiresApproval(action)for Studio's exposure surface.Wiring
AIServicePluginOptionsgainsenableActionApproval?: boolean(defaultfalse). Whentrueand anIDataEngineis available, dangerous actions are registered and routed through the queue.Internals
actionSkipReason()acceptsenableActionApproval+aiServicein its ctx and stops returning"requires confirmation"/"mode='delete'"/"variant='danger'"when HITL is wired.registerActionsAsTools()pre-registers a bypass-approval dispatcher per dangerous tool viaaiService.registerPendingActionDispatcher(toolName, fn); approval calls back into the same code path withenableActionApprovalflipped off, so a single handler implementation serves both proposal and execution.createActionToolHandler()short-circuits toproposePendingAction()whenenableActionApproval && actionRequiresApproval(action) && ctx.aiService?.proposePendingAction.Out of scope (deferred)
Slack/email notifications, approver routing (any signed-in user can approve in v1), auto-expiry of pending requests, resuming the same LLM turn after approval (operators get a fresh assistant message instead).
bce47a0: Polish Studio HITL pending-action inbox UI
The
AiPendingActionViewshipped byservice-aiis now an actual operatorconsole rather than a flat grid:
(
navigation: { mode: 'drawer', view: 'detail' }) with four sections:Proposal · Tool input · Conversation context · Decision.
tool_input,result, anderrorso structured toolarguments and responses are readable without copy-pasting into a formatter.
type: 'datetime-relative') onproposed_at/decided_atcolumns and form fields.Field.lookupreferencesto
ai_conversations/ai_messagesare surfaced in a collapsed"Conversation context" section, giving operators one-click access from a
pending action back to the chat that proposed it.
visibleOnpredicates —rejection_reasononly appears for rejected rows,
erroronly for failed rows, etc.rowActionspointing at the existing
approve_pending_action/reject_pending_actionobject actions; the same actions also render in the drawer header.
Snapshot-style tests in
__tests__/ai-pending-action.view.test.tslock theshape so future Studio contract changes (widget renames, navigation modes)
fail loudly in one place.
This is a metadata-only change — Studio (
@object-ui/studio) interprets thenew view automatically. No backend, REST, or HITL semantics changed; the
end-to-end demos in
examples/app-todo/test/ai-hitl*.test.tscontinue topass unmodified.
Patch Changes
13a4f38: Actions-as-tools Phase 2: the AI tool runtime can now dispatch
type:'api'andtype:'flow'actions in addition totype:'script'.ApiActionClientinterface andcreateFetchApiClient({ baseUrl, headers, fetch })factory — default fetch-based dispatch resolves relativetargetpaths againstbaseUrl, throws on non-2xx with${method} ${url} → ${status}: ${body}, and JSON-parses the response.buildApiRequestBody(action, args, record, recordId)helper — honoursbodyShape.wrap,recordIdParam+recordIdField(defaults to'id'), and mergesbodyExtralast so constants win.ActionToolsContextextended (additive):automation,apiClient,apiBaseUrl,apiHeaders.actionSkipReason()gains an optional secondctxparameter that returns precise wiring-availability reasons ('no automation service available','no apiClient or apiBaseUrl configured'). Studio-only types (url/modal/form) and all dangerous variants (confirmText,mode:'delete',variant:'danger') remain skipped.AIServicePluginoptions acceptapiActionBaseUrl(falls back toOS_AI_ACTION_API_BASE_URL) andapiActionHeaders; the plugin now resolves theautomationservice silently and threads everything intoregisterActionsAsTools.Net result: every non-destructive declarative action with a target —
script,api,flow— is now LLM-callable end-to-end as soon as the corresponding wiring is in place.bce47a0: HITL Phase 3 — end-to-end demos + bug fix in handler-engine adapter.
Two runnable integration demos for the action-approval queue ship under
examples/app-todo/test/:ai-hitl.test.ts— drives the tool registry directly (no LLM). Assertsvariant:'danger'actions register as tools, invocation returnspending_approval, row persists,approvePendingAction(id, actor)re-runs the handler, row flips toexecuted. Reject path covered too. Run withpnpm --filter @example/app-todo test:hitl.ai-hitl-llm.test.ts— same scenario behind a real model on Vercel AI Gateway. The LLM autonomously picksaction_delete_completed, the framework gates the call withpending_approval, the model summarises the wait without retrying, and the operator-side approve completes the deletion. Gated onAI_GATEWAY_API_KEY. Run withAI_GATEWAY_API_KEY=... pnpm --filter @example/app-todo test:hitl:llm.While wiring the demos, two bugs surfaced in the bypass-approval dispatcher and the handler-engine adapter:
Bulk delete from declarative handlers was silently failing. The adapter built by
buildHandlerEngineAdapter()wrapped multi-id deletes asengine.delete(obj, { where: { id: { $in: ids } } }), butObjectQLEngine.delete()prefers the scalaridbranch wheneverwhere.idis set — so the{ $in: [...] }object was forwarded todriver.delete(scalar)and rejected as"Wrong API use: tried to bind a value of an unknown type ([object Object])". The adapter now loops scalar deletes, which is correct and driver-agnostic.Approval pathway swallowed handler errors.
createActionToolHandlerreturns a{ ok: false, error }envelope on failure rather than throwing. The pre-registered bypass dispatcher just JSON-parsed and returned that envelope, soapprovePendingActionthought the run succeeded and flipped the row toexecuted. The dispatcher now treatsok === falseas a thrown error, so failed approvals are correctly persisted asstatus: 'failed'with the original message.Also: added
delete/remove/purge/destroy/erasetoMemoryLLMAdapter.ACTION_VERBSso the in-memory adapter can route delete-style intents during tests that don't have a real LLM.Docs:
content/docs/guides/ai-capabilities.mdxnow points at the two integration demos with copy-pasteable run commands.449e35d: Real-LLM smoke test for the
data_chatagent loop, plus twoquery_datarobustness fixes shaken out by running it against
openai/gpt-4.1-miniviathe Vercel AI Gateway.
query_datatool fixesRemoved the LLM-controllable
modelparameter from the public toolschema. Frontier models were hallucinating
text-davinci-003and otherlong-dead model ids, breaking every plan generation.
Switched the structured-output filter shape from
z.record(...)(whichemits
propertyNamesin JSON Schema, rejected by OpenAI StructuredOutputs) to a
whereJsonstring field. The model emits a JSON-encodedObjectQL filter; the tool parses & validates it before execution. This
also fixes a parallel issue with OpenAI's strict mode requiring every
property to appear in
required.Switched all optional fields to
.nullable()so the planner Zod schemasatisfies OpenAI Structured Outputs' "every property must be required"
rule.
Beefed up the planner system prompt with explicit operator hints — most
importantly: use
$containsfor partial string matches ("task named Foo"→{"subject":{"$contains":"Foo"}}), not equality. Without thishint the model defaulted to exact-match equality and never found
anything.
New smoke test
examples/app-todo/test/ai-llm.test.ts(gated onAI_GATEWAY_API_KEY):boots the full ObjectStack, registers
query_data+ the six auto-generatedaction_*tools, sends "Please mark the 'Build' task as complete." to areal LLM, and asserts that
the model picked the right tools in the right order
(
query_data→action_complete_task),a task row actually flipped to
completed, andan
ai_traceschat_with_toolsrow landed.Run with:
pnpm --filter @example/app-todo test:llm.Verified end-to-end against
openai/gpt-4.1-mini(~6.6 s, 2 tool calls,1 task completed, trace persisted).
Updated dependencies [b4c74a9]
@objectstack/account@6.2.0
Patch Changes
@objectstack/hono@6.2.0
Patch Changes
@objectstack/cli@6.2.0
Patch Changes
@objectstack/client@6.2.0
Patch Changes
@objectstack/client-react@6.2.0
Patch Changes
@objectstack/core@6.2.0
Patch Changes
@objectstack/formula@6.2.0
Patch Changes
@objectstack/metadata@6.2.0
Patch Changes
@objectstack/metadata-fs@6.2.0
Patch Changes
@objectstack/objectql@6.2.0
Patch Changes
@objectstack/observability@6.2.0
Patch Changes
@objectstack/platform-objects@6.2.0
Patch Changes
@objectstack/driver-memory@6.2.0
Patch Changes
@objectstack/driver-mongodb@6.2.0
Patch Changes
@objectstack/driver-sql@6.2.0
Patch Changes
@objectstack/driver-sqlite-wasm@6.2.0
Patch Changes
@objectstack/driver-turso@6.2.0
Patch Changes
@objectstack/plugin-approvals@6.2.0
Patch Changes
@objectstack/plugin-audit@6.2.0
Patch Changes
@objectstack/plugin-dev@6.2.0
Patch Changes
@objectstack/plugin-email@6.2.0
Patch Changes
@objectstack/plugin-hono-server@6.2.0
Patch Changes
@objectstack/plugin-mcp-server@6.2.0
Patch Changes
@objectstack/plugin-msw@6.2.0
Patch Changes
@objectstack/plugin-reports@6.2.0
Patch Changes
@objectstack/plugin-security@6.2.0
Patch Changes
@objectstack/plugin-sharing@6.2.0
Patch Changes
@objectstack/plugin-webhooks@6.2.0
Patch Changes
@objectstack/rest@6.2.0
Patch Changes
@objectstack/runtime@6.2.0
Patch Changes
dbb54e1: Fix: AI streaming endpoints (e.g.
POST /api/v1/ai/assistant/chat) nowactually stream Server-Sent Events instead of returning the stream
descriptor JSON-serialized.
The shared
sendResultBase()indispatcher-plugin.tspreviously had a// pass through as JSON for nowTODO, so any dispatcher route whoseresult.resultwas a stream descriptor ({ type: 'stream', events, headers, ... }) would respond with a literal{"type":"stream", "events":{},"vercelDataStream":true,...}body — breaking@object-ui/plugin-chatbotand any other Vercel-AI-SDK consumer.The dispatcher now:
Detects
{ type: 'stream' | stream: true, events, headers? }shapes.Applies the route-provided headers (defaults to
text/event-stream/no-cache/keep-alivewhen none are supplied).Performs an empty
res.write('')synchronously so the Hono adapter'sisStreamingflag flips before the route handler resolves (the adapterwould otherwise close the body before the first async chunk lands).
Drains the
AsyncIterable<string>of pre-encoded SSE chunks in thebackground, calling
res.end()when the iterator finishes or errors.Non-stream
result.resultpayloads keep the existing JSON behaviour.Updated dependencies [b4c74a9]
Updated dependencies [b4c74a9]
@objectstack/service-analytics@6.2.0
Patch Changes
@objectstack/service-automation@6.2.0
Patch Changes
@objectstack/service-cache@6.2.0
Patch Changes
@objectstack/service-cluster@5.1.5
Patch Changes
@objectstack/service-cluster-redis@5.1.5
Patch Changes
@objectstack/service-feed@6.2.0
Patch Changes
@objectstack/service-i18n@6.2.0
Patch Changes
@objectstack/service-job@6.2.0
Patch Changes
@objectstack/service-package@6.2.0
Patch Changes
@objectstack/service-queue@6.2.0
Patch Changes
@objectstack/service-realtime@6.2.0
Patch Changes
@objectstack/service-settings@6.2.0
Patch Changes
@objectstack/service-storage@6.2.0
Patch Changes
@objectstack/spec@6.2.0
Patch Changes
b4c74a9: Actions-as-tools Phase 3 — Human-In-The-Loop approval queue.
Dangerous declarative actions (
confirmText,mode:'delete',variant:'danger') can now be exposed to the LLM safely. Instead of being skipped outright, they are registered as tools whose handler enqueues a pending request and returns{ status: 'pending_approval', pendingActionId }to the model. A human approves (or rejects) from Studio's pending-actions inbox; the service then re-runs the exact same dispatcher.New surface
ai_pending_actions(id, conversation_id?, message_id?, object_name, action_name, tool_name, tool_input, status [pending|approved|executed|failed|rejected], result?, error?, rejection_reason?, proposed_by, decided_by?, proposed_at, decided_at?).AiPendingActionViewwithpending/executed/rejected/failedsub-views and per-row Approve / Reject API actions.IAIService(all optional, gated on a wiredIDataEngine):proposePendingAction(input) → { id }approvePendingAction(id, actorId) → { status, result?, error? }rejectPendingAction(id, actorId, reason?)listPendingActions(filter?) → PendingActionRow[]PendingActionStatus,ProposePendingActionInput,PendingActionRow.GET /api/v1/ai/pending-actions(ai:read)GET /api/v1/ai/pending-actions/:id(ai:read)POST /api/v1/ai/pending-actions/:id/approve(ai:approve)POST /api/v1/ai/pending-actions/:id/reject(ai:approve)actionRequiresApproval(action)for Studio's exposure surface.Wiring
AIServicePluginOptionsgainsenableActionApproval?: boolean(defaultfalse). Whentrueand anIDataEngineis available, dangerous actions are registered and routed through the queue.Internals
actionSkipReason()acceptsenableActionApproval+aiServicein its ctx and stops returning"requires confirmation"/"mode='delete'"/"variant='danger'"when HITL is wired.registerActionsAsTools()pre-registers a bypass-approval dispatcher per dangerous tool viaaiService.registerPendingActionDispatcher(toolName, fn); approval calls back into the same code path withenableActionApprovalflipped off, so a single handler implementation serves both proposal and execution.createActionToolHandler()short-circuits toproposePendingAction()whenenableActionApproval && actionRequiresApproval(action) && ctx.aiService?.proposePendingAction.Out of scope (deferred)
Slack/email notifications, approver routing (any signed-in user can approve in v1), auto-expiry of pending requests, resuming the same LLM turn after approval (operators get a fresh assistant message instead).
@objectstack/types@6.2.0
Patch Changes
@objectstack/express@6.2.0
@objectstack/fastify@6.2.0
@objectstack/nestjs@6.2.0
@objectstack/nextjs@6.2.0
@objectstack/nuxt@6.2.0
@objectstack/sveltekit@6.2.0
create-objectstack@6.2.0
@objectstack/metadata-core@6.2.0
objectstack-vscode@6.2.0
@objectstack/example-crm@4.0.15
Patch Changes
@example/app-todo@4.0.15
Patch Changes
449e35d: Real-LLM smoke test for the
data_chatagent loop, plus twoquery_datarobustness fixes shaken out by running it against
openai/gpt-4.1-miniviathe Vercel AI Gateway.
query_datatool fixesRemoved the LLM-controllable
modelparameter from the public toolschema. Frontier models were hallucinating
text-davinci-003and otherlong-dead model ids, breaking every plan generation.
Switched the structured-output filter shape from
z.record(...)(whichemits
propertyNamesin JSON Schema, rejected by OpenAI StructuredOutputs) to a
whereJsonstring field. The model emits a JSON-encodedObjectQL filter; the tool parses & validates it before execution. This
also fixes a parallel issue with OpenAI's strict mode requiring every
property to appear in
required.Switched all optional fields to
.nullable()so the planner Zod schemasatisfies OpenAI Structured Outputs' "every property must be required"
rule.
Beefed up the planner system prompt with explicit operator hints — most
importantly: use
$containsfor partial string matches ("task named Foo"→{"subject":{"$contains":"Foo"}}), not equality. Without thishint the model defaulted to exact-match equality and never found
anything.
New smoke test
examples/app-todo/test/ai-llm.test.ts(gated onAI_GATEWAY_API_KEY):boots the full ObjectStack, registers
query_data+ the six auto-generatedaction_*tools, sends "Please mark the 'Build' task as complete." to areal LLM, and asserts that
the model picked the right tools in the right order
(
query_data→action_complete_task),a task row actually flipped to
completed, andan
ai_traceschat_with_toolsrow landed.Run with:
pnpm --filter @example/app-todo test:llm.Verified end-to-end against
openai/gpt-4.1-mini(~6.6 s, 2 tool calls,1 task completed, trace persisted).
Updated dependencies [13a4f38]
Updated dependencies [b4c74a9]
Updated dependencies [bce47a0]
Updated dependencies [bce47a0]
Updated dependencies [449e35d]
Updated dependencies [dbb54e1]