@mindstudio-ai/remy 0.1.305 → 0.1.306

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -112,17 +112,29 @@ await chat.deleteThread(thread.id);
112
112
  await chat.claimThread(thread.id);
113
113
  ```
114
114
 
115
- **Client tools** — a tool whose effect happens in the browser (open a sheet, navigate, highlight) is declared with `target: "client"` and a `name` + inline `inputSchema` instead of a `method` (names must not collide with method ids; the schema is authored — there's no method contract to derive it from). The agent's invocation arrives as the `client_tool_call` stream event / the `onClientToolCall` callback on `sendMessage`; run the action there. Fire-and-forget on this surface: the agent is told the action was displayed and keeps going — the user's next message closes the loop.
115
+ **Client tools** — a tool whose effect happens in the browser (open a sheet, pick a file, confirm an action) is declared with `target: "client"` and a `name` + inline `inputSchema` instead of a `method` (names must not collide with method ids; the schema is authored — there's no method contract to derive it from). Register a handler and its **return value becomes the tool result**, so the agent learns what happened rather than assuming it did:
116
116
 
117
117
  ```js
118
- await chat.sendMessage(thread.id, text, {
119
- onText: (delta) => append(delta),
120
- onClientToolCall: (name, input) => {
121
- if (name === 'showVerification') openVerifySheet(input);
122
- },
118
+ chat.registerClientTool('pickFile', async ({ prompt }) => {
119
+ const file = await openFilePicker(prompt);
120
+ return file ? { path: file.path } : { cancelled: true };
123
121
  });
122
+
123
+ // Holding the turn on a person: the handler resolves when they decide.
124
+ chat.registerClientTool(
125
+ 'confirmDeploy',
126
+ ({ summary }) =>
127
+ new Promise((resolve) => {
128
+ showApprovalDialog(summary, {
129
+ onApprove: (note) => resolve({ approved: true, note }),
130
+ onReject: (reason) => resolve({ approved: false, reason }),
131
+ });
132
+ }),
133
+ );
124
134
  ```
125
135
 
136
+ The agent waits while the handler runs, up to 15 minutes — which is what makes confirm-before-acting a client tool rather than something you build a queue for. The SDK always answers, so the agent is never stuck: the return value, `{ error }` if the handler threw, `result_too_large` past ~32KB serialized, and `unhandled_client_tool` immediately when nothing is registered for that name; the platform supplies `client_timeout` if the window passes and `client_disconnected` if the page closes. Handlers live for the client's lifetime rather than one message. `onClientToolCall` on `sendMessage` behaves the same way for a one-off — whatever it returns is the result — and is consulted only when no handler is registered.
137
+
126
138
  **Sending messages (streaming):**
127
139
 
128
140
  `sendMessage` streams the agent's response via SSE. Use named callbacks for common events:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mindstudio-ai/remy",
3
- "version": "0.1.305",
3
+ "version": "0.1.306",
4
4
  "description": "Remy coding agent",
5
5
  "repository": {
6
6
  "type": "git",