@abide/abide 0.106.0 → 0.107.0
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.
- package/CHANGELOG.md +10 -0
- package/docs/REGISTRY.md +4 -4
- package/docs/RULEBOOK.md +19 -3
- package/docs/abide.md +18 -8
- package/package.json +1 -1
- package/src/compiler/classifyTemplate.ts +5 -3
- package/src/compiler/emitClient.ts +6 -4
- package/src/compiler/invocationProps.ts +1 -1
- package/src/server/BRIDGE_VERSION.ts +1 -1
- package/src/server/assistant.ts +2 -1
- package/src/server/claudeApi.ts +12 -4
- package/src/server/claudeCode.ts +9 -4
- package/src/ui/bindElement.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @abide/abide
|
|
2
2
|
|
|
3
|
+
## 0.107.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- bd2a74f: Breaking: an assistant announces a tool call as the model starts writing it, and a site may ask the visitor's Claude Code for built-in tools ([`c959804`](https://github.com/briancray/abide/commit/c959804fd19c3e99fe439f3f1120f1ef13f42ff8))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- bd2a74f: a bind:element callback is handed a connected node whose blocks and components have built, and bind:element on a component is a build error ([`e15fbee`](https://github.com/briancray/abide/commit/e15fbee6f7c780dab2105ca245dd79dbb4a2e317))
|
|
12
|
+
|
|
3
13
|
## 0.106.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/docs/REGISTRY.md
CHANGED
|
@@ -321,9 +321,9 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
321
321
|
| --- | --- | --- | --- |
|
|
322
322
|
| `assistant` | `(messages: AssistantMessage[], provider: Provider, options?: AssistantOptions) => AsyncGenerator<AssistantEvent>` | A conversation with a model, as the events it produces. | 44.1, 44.2, 44.3, 44.4, 44.21 |
|
|
323
323
|
| `AssistantMessage` | `{ role: 'user' \| 'assistant'; content: string }` | One turn of the transcript a caller sends. | 44.3, 44.4 |
|
|
324
|
-
| `AssistantEvent` | `{ type: 'text'; text: string } \| { type: 'tool'; id: string; name: string; input: unknown } \| { type: 'result'; id: string; text: string; failed: boolean } \| { type: 'done'; stop: string; usage: { input: number; output: number } }` | What a conversation produces: text, a tool call, its result, and the end. | 44.2, 44.11 |
|
|
324
|
+
| `AssistantEvent` | `{ type: 'text'; text: string } \| { type: 'tool'; id: string; name: string } \| { type: 'input'; id: string; input: unknown } \| { type: 'result'; id: string; text: string; failed: boolean } \| { type: 'done'; stop: string; usage: { input: number; output: number } }` | What a conversation produces: text, a tool call as it starts, its input once written, its result, and the end. | 44.2, 44.11, 44.29 |
|
|
325
325
|
| `AssistantOptions` | `{ mcp?: boolean; maxTurns?: number }` | What `assistant` takes beside a provider. | 44.6, 44.8, 44.11 |
|
|
326
|
-
| `Provider` | `{ run(messages: AssistantMessage[], tools: Toolbox, limits: { maxTurns: number; signal: AbortSignal }): AsyncGenerator<AssistantEvent> }` | What runs a conversation. | 44.2 |
|
|
326
|
+
| `Provider` | `{ run(messages: AssistantMessage[], tools: Toolbox, limits: { maxTurns: number; signal: AbortSignal }): AsyncGenerator<AssistantEvent> }` | What runs a conversation. | 44.2, 44.29 |
|
|
327
327
|
| `Toolbox` | `{ list: ToolDefinition[]; call(name: string, input: unknown): Promise<{ text: string; failed: boolean }> }` | The app's MCP tools, called as the asker. | 44.6, 44.7 |
|
|
328
328
|
| `ToolDefinition` | `{ name: string; description: string; inputSchema: unknown; annotations: { readOnlyHint: boolean; destructiveHint: boolean; idempotentHint: boolean }; outputSchema: unknown }` | A tool as the app's MCP surface lists it. | 20.14, 20.16, 44.6 |
|
|
329
329
|
|
|
@@ -339,7 +339,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
339
339
|
| Name | Signature | Meaning | Rules |
|
|
340
340
|
| --- | --- | --- | --- |
|
|
341
341
|
| `claudeCode` | `(config?: ClaudeCodeConfig) => Provider` | The visitor's own Claude Code, reached through the bridge paired with their browser, as a provider. | 44.5, 44.13, 44.17, 44.18, 44.19, 44.24, 44.25, 44.28 |
|
|
342
|
-
| `ClaudeCodeConfig` | `{ model?: string; fallbackModel?: string; systemPrompt?: string; appendSystemPrompt?: string; effort?: 'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max' }` | The Claude Code options a site may set for a turn. | 44.16 |
|
|
342
|
+
| `ClaudeCodeConfig` | `{ model?: string; fallbackModel?: string; systemPrompt?: string; appendSystemPrompt?: string; effort?: 'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max'; maxBudgetUsd?: number; betas?: string[]; disallowedTools?: string[]; tools?: string[] }` | The Claude Code options a site may set for a turn, and the built-in tools it asks the visitor for. | 44.16, 44.30 |
|
|
343
343
|
| `claudeCode.bridgeCommand` | `() => { command: string; expires: number }` | The command that pairs a bridge with this browser. | 44.14 |
|
|
344
344
|
| `claudeCode.bridge` | `() => AsyncGenerator<BridgeStatus>` | This browser's pairing, as it changes. | 44.20, 44.22 |
|
|
345
345
|
| `BridgeStatus` | `{ paired: boolean; command: string \| undefined }` | Whether a bridge is paired, and the command that pairs one where none is. | 44.20 |
|
|
@@ -537,7 +537,7 @@ type Gated<Gate, Accepted> = [Schema<Accepted>] extends [Gate] ? never : Failed<
|
|
|
537
537
|
| `bind:open` | The same, on a `<details>`. | 32.7 |
|
|
538
538
|
| `bind:group` | Radio or checkbox membership. | 32.8 |
|
|
539
539
|
| `bind:value={{get, set}}` | Two-way bind over an explicit accessor pair, on an element or a component. | 32.5, 32.6 |
|
|
540
|
-
| `bind:element={Reactive<Element> \| ((element: Element) => void \| Disposer)}` | A node reference. | 32.9, 32.38, 32.66 |
|
|
540
|
+
| `bind:element={Reactive<Element> \| ((element: Element) => void \| Disposer)}` | A node reference. | 32.9, 32.38, 32.66, 32.68, 32.69 |
|
|
541
541
|
| `class:name={cond}` | Toggles a class. | 32.10 |
|
|
542
542
|
| `style:prop={value}` | Sets one style property. | 32.10, 32.19 |
|
|
543
543
|
| `{...expr}` | Spreads props or attributes. | 32.11, 32.37, 33.12, 33.13 |
|
package/docs/RULEBOOK.md
CHANGED
|
@@ -1959,6 +1959,12 @@ markup.
|
|
|
1959
1959
|
32.67 A `{#for}` MUST keep the row and the nodes of a key it keeps when that key's item is a
|
|
1960
1960
|
different value, and MUST update the row's bindings that read the item in place.
|
|
1961
1961
|
|
|
1962
|
+
32.68 A `bind:element` value MUST be handed its element after a region's build has put that element
|
|
1963
|
+
in the region, and after every block and component inside the element has built, so a callback
|
|
1964
|
+
reading layout, querying its descendants or calling `focus()` acts on a connected, whole node.
|
|
1965
|
+
|
|
1966
|
+
32.69 `bind:element` on a component MUST be a build error.
|
|
1967
|
+
|
|
1962
1968
|
# 33. Props
|
|
1963
1969
|
|
|
1964
1970
|
33.1 `props` MUST be callable from a `<script>` block only, and calling it from a `<script module>`
|
|
@@ -3060,10 +3066,13 @@ and MUST refuse 409 where none is paired.
|
|
|
3060
3066
|
44.14 A code `claudeCode.bridgeCommand` mints MUST pair one bridge with the browser that asked for
|
|
3061
3067
|
it, once, and MUST NOT pair once it has expired.
|
|
3062
3068
|
|
|
3063
|
-
44.15 A bridge MUST run Claude Code with
|
|
3064
|
-
|
|
3069
|
+
44.15 A bridge MUST run Claude Code with no MCP server but the bridge's own, in an empty directory
|
|
3070
|
+
removed when the run ends, and with no built-in tool and no setting source the visitor did not pass
|
|
3071
|
+
it after `--`.
|
|
3065
3072
|
|
|
3066
|
-
44.16 A bridge MUST
|
|
3073
|
+
44.16 A bridge MUST lay each option a site sets but `tools` (44.30) on as Claude Code's flag of that
|
|
3074
|
+
name, MUST fail a turn whose config sets any option `ClaudeCodeConfig` does not name, and MUST lay
|
|
3075
|
+
an option the visitor passed after `--` over the site's.
|
|
3067
3076
|
|
|
3068
3077
|
44.17 An MCP request a bridge's Claude Code makes MUST be answered from the `Toolbox` of the turn it
|
|
3069
3078
|
was made in.
|
|
@@ -3098,3 +3107,10 @@ the stream is open.
|
|
|
3098
3107
|
|
|
3099
3108
|
44.28 A bridge whose stream from `/__abide/bridge` carries no line for 45 seconds MUST end it and
|
|
3100
3109
|
redial it as 44.25 says.
|
|
3110
|
+
|
|
3111
|
+
44.29 A `Provider` MUST yield a tool call's `tool` event when the model starts writing the call,
|
|
3112
|
+
and its `input` event, with the same `id`, once the call is written.
|
|
3113
|
+
|
|
3114
|
+
44.30 A built-in tool MUST be available to a turn only where the site's `tools` names it and the
|
|
3115
|
+
visitor's `--tools` does, MUST be approved without asking unless the visitor passed `--allowedTools`,
|
|
3116
|
+
and the bridge MUST say once each tool the site asked for that the visitor did not grant.
|
package/docs/abide.md
CHANGED
|
@@ -5253,8 +5253,11 @@ const events = reactive(() =>
|
|
|
5253
5253
|
{#for event of events}
|
|
5254
5254
|
{#if event.type === 'tool'}
|
|
5255
5255
|
<li><span>tool call</span>
|
|
5256
|
+
<p class="font-mono text-chrome">{event.name}</p></li>
|
|
5257
|
+
{:else if event.type === 'input'}
|
|
5258
|
+
<li><span>with input</span>
|
|
5256
5259
|
<p class="font-mono text-chrome">
|
|
5257
|
-
{
|
|
5260
|
+
{JSON.stringify(event.input)}
|
|
5258
5261
|
</p></li>
|
|
5259
5262
|
{:else if event.type === 'result'}
|
|
5260
5263
|
<li><span>your handler answered</span>
|
|
@@ -5286,7 +5289,8 @@ const recorded: Provider = {
|
|
|
5286
5289
|
)
|
|
5287
5290
|
const name = tool?.name ?? ''
|
|
5288
5291
|
const input = { name: 'Ada' }
|
|
5289
|
-
yield { type: 'tool', id: 'toolu_1', name
|
|
5292
|
+
yield { type: 'tool', id: 'toolu_1', name }
|
|
5293
|
+
yield { type: 'input', id: 'toolu_1', input }
|
|
5290
5294
|
const answered = await tools.call(name, input)
|
|
5291
5295
|
yield { type: 'result', id: 'toolu_1', ...answered }
|
|
5292
5296
|
yield { type: 'text', text: 'Ada Lovelace is at Analytical Engines.' }
|
|
@@ -5343,7 +5347,7 @@ test('the model calls the CRM search, through the app', async () => {
|
|
|
5343
5347
|
| --- | --- |
|
|
5344
5348
|
| `AssistantMessage` | One turn of the transcript, `{ role, content }`. The last is the user's. |
|
|
5345
5349
|
| `AssistantOptions` | `mcp` to offer the tools, and `maxTurns`, 10 by default, to cap the model's turns in one call. |
|
|
5346
|
-
| `AssistantEvent` | What the page reads: `text`, `tool
|
|
5350
|
+
| `AssistantEvent` | What the page reads: `text`, `tool` as a call starts, `input` once it is written, `result`, then `done` with the stop reason and token usage. The same events from every provider. |
|
|
5347
5351
|
| `Provider` | What runs the conversation: one method, `run`. Write one for another model, or a recording for a test. |
|
|
5348
5352
|
| `Toolbox` | What a provider is handed: `list` of the tools, and `call` to run one as the asker. |
|
|
5349
5353
|
| `ToolDefinition` | One tool in `list`: its name, description and input schema. |
|
|
@@ -5620,7 +5624,13 @@ test('unpaired: asking is refused, the bridge shows a command', async () => {
|
|
|
5620
5624
|
})
|
|
5621
5625
|
```
|
|
5622
5626
|
|
|
5623
|
-
`claudeCode` sends the conversation to Claude Code on the asker's machine, on their own sign-in and plan. Its config, `ClaudeCodeConfig`, is Claude Code's own option names: `model`, `fallbackModel`, `systemPrompt`, `appendSystemPrompt` and `
|
|
5627
|
+
`claudeCode` sends the conversation to Claude Code on the asker's machine, on their own sign-in and plan. Its config, `ClaudeCodeConfig`, is Claude Code's own option names, each passed as its flag: `model`, `fallbackModel`, `systemPrompt`, `appendSystemPrompt`, `effort`, `maxBudgetUsd`, `betas` and `disallowedTools`. Permissions, directories and settings are not the site's to set.
|
|
5628
|
+
|
|
5629
|
+
`tools` asks for Claude Code's built-in tools, and the visitor decides. A tool runs only where they granted it after the command's `--`, and the bridge tells them about any it was asked for and not given. Anything else after `--` goes to Claude Code as written, and overrides what the site set.
|
|
5630
|
+
|
|
5631
|
+
```
|
|
5632
|
+
bunx @abide/bridge <site> <code> -- --tools WebSearch,WebFetch
|
|
5633
|
+
```
|
|
5624
5634
|
|
|
5625
5635
|
The visitor pairs once per visit by running a command, which dials out to the site. Asking with nothing paired is refused 409.
|
|
5626
5636
|
|
|
@@ -7699,7 +7709,7 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
7699
7709
|
|
|
7700
7710
|
| Name | Signature | Meaning | Rules |
|
|
7701
7711
|
| --- | --- | --- | --- |
|
|
7702
|
-
| `AssistantEvent` | `{ type: 'text'; text: string } \| { type: 'tool'; id: string; name: string; input: unknown } \| { type: 'result'; id: string; text: string; failed: boolean } \| { type: 'done'; stop: string; usage: { input: number; output: number } }` | What a conversation produces: text, a tool call, its result, and the end. | [44.2](/rulebook#44.2), [44.11](/rulebook#44.11) |
|
|
7712
|
+
| `AssistantEvent` | `{ type: 'text'; text: string } \| { type: 'tool'; id: string; name: string } \| { type: 'input'; id: string; input: unknown } \| { type: 'result'; id: string; text: string; failed: boolean } \| { type: 'done'; stop: string; usage: { input: number; output: number } }` | What a conversation produces: text, a tool call as it starts, its input once written, its result, and the end. | [44.2](/rulebook#44.2), [44.11](/rulebook#44.11), [44.29](/rulebook#44.29) |
|
|
7703
7713
|
|
|
7704
7714
|
## Taught in
|
|
7705
7715
|
|
|
@@ -7735,7 +7745,7 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
7735
7745
|
|
|
7736
7746
|
| Name | Signature | Meaning | Rules |
|
|
7737
7747
|
| --- | --- | --- | --- |
|
|
7738
|
-
| `Provider` | `{ run(messages: AssistantMessage[], tools: Toolbox, limits: { maxTurns: number; signal: AbortSignal }): AsyncGenerator<AssistantEvent> }` | What runs a conversation. | [44.2](/rulebook#44.2) |
|
|
7748
|
+
| `Provider` | `{ run(messages: AssistantMessage[], tools: Toolbox, limits: { maxTurns: number; signal: AbortSignal }): AsyncGenerator<AssistantEvent> }` | What runs a conversation. | [44.2](/rulebook#44.2), [44.29](/rulebook#44.29) |
|
|
7739
7749
|
|
|
7740
7750
|
## Taught in
|
|
7741
7751
|
|
|
@@ -7846,7 +7856,7 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
7846
7856
|
|
|
7847
7857
|
| Name | Signature | Meaning | Rules |
|
|
7848
7858
|
| --- | --- | --- | --- |
|
|
7849
|
-
| `ClaudeCodeConfig` | `{ model?: string; fallbackModel?: string; systemPrompt?: string; appendSystemPrompt?: string; effort?: 'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max' }` | The Claude Code options a site may set for a turn. | [44.16](/rulebook#44.16) |
|
|
7859
|
+
| `ClaudeCodeConfig` | `{ model?: string; fallbackModel?: string; systemPrompt?: string; appendSystemPrompt?: string; effort?: 'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max'; maxBudgetUsd?: number; betas?: string[]; disallowedTools?: string[]; tools?: string[] }` | The Claude Code options a site may set for a turn, and the built-in tools it asks the visitor for. | [44.16](/rulebook#44.16), [44.30](/rulebook#44.30) |
|
|
7850
7860
|
|
|
7851
7861
|
## Taught in
|
|
7852
7862
|
|
|
@@ -8607,7 +8617,7 @@ Generated surfaces: what is written in place rather than imported.
|
|
|
8607
8617
|
| `bind:open` | The same, on a `<details>`. | [32.7](/rulebook#32.7) |
|
|
8608
8618
|
| `bind:group` | Radio or checkbox membership. | [32.8](/rulebook#32.8) |
|
|
8609
8619
|
| `bind:value={{get, set}}` | Two-way bind over an explicit accessor pair, on an element or a component. | [32.5](/rulebook#32.5), [32.6](/rulebook#32.6) |
|
|
8610
|
-
| `bind:element={Reactive<Element> \| ((element: Element) => void \| Disposer)}` | A node reference. | [32.9](/rulebook#32.9), [32.38](/rulebook#32.38), [32.66](/rulebook#32.66) |
|
|
8620
|
+
| `bind:element={Reactive<Element> \| ((element: Element) => void \| Disposer)}` | A node reference. | [32.9](/rulebook#32.9), [32.38](/rulebook#32.38), [32.66](/rulebook#32.66), [32.68](/rulebook#32.68), [32.69](/rulebook#32.69) |
|
|
8611
8621
|
| `class:name={cond}` | Toggles a class. | [32.10](/rulebook#32.10) |
|
|
8612
8622
|
| `style:prop={value}` | Sets one style property. | [32.10](/rulebook#32.10), [32.19](/rulebook#32.19) |
|
|
8613
8623
|
| `{...expr}` | Spreads props or attributes. | [32.11](/rulebook#32.11), [32.37](/rulebook#32.37), [33.12](/rulebook#33.12), [33.13](/rulebook#33.13) |
|
package/package.json
CHANGED
|
@@ -464,13 +464,15 @@ export function isParserOwned(lowerTag: string): boolean {
|
|
|
464
464
|
/**
|
|
465
465
|
* The key a component's attribute passes a prop under, or `undefined` where it is no prop.
|
|
466
466
|
*
|
|
467
|
-
* 32.6, 32.10 — a `bind:` handing over a `Reactive` keys the name after it, and any other
|
|
468
|
-
* — `class:`, `style:`, a `bind:` with nothing bound — is an element's own.
|
|
467
|
+
* 32.6, 32.10, 32.69 — a `bind:` handing over a `Reactive` keys the name after it, and any other
|
|
468
|
+
* `:` name — `class:`, `style:`, `bind:element`, a `bind:` with nothing bound — is an element's own.
|
|
469
|
+
* Read as a prop, `bind:element` was one named `element` the child never declared, and the
|
|
470
|
+
* callback never ran. The build writes the
|
|
469
471
|
* props record by this and the checker projects it by this, so a tag is held to what it sends.
|
|
470
472
|
*/
|
|
471
473
|
export function propKeyOf(attribute: Attribute): string | undefined {
|
|
472
474
|
if (attribute.lowerName.startsWith('bind:'))
|
|
473
|
-
return attribute.expression
|
|
475
|
+
return attribute.expression && !isElementBind(attribute.lowerName)
|
|
474
476
|
? attribute.name.slice('bind:'.length)
|
|
475
477
|
: undefined
|
|
476
478
|
return attribute.name.includes(':') ? undefined : attribute.name
|
|
@@ -558,9 +558,11 @@ function emitRegion(sink: Cursor, region: RegionEmission): RegionEmission {
|
|
|
558
558
|
|
|
559
559
|
for (const line of walkTo(positions, live, lowering)) chain.push(line)
|
|
560
560
|
|
|
561
|
-
// THE UNITS
|
|
562
|
-
//
|
|
563
|
-
//
|
|
561
|
+
// THE UNITS — text, listeners, attributes, the regions, then the node handed over. The walk
|
|
562
|
+
// does not depend on the order.
|
|
563
|
+
// 32.68 — A `bind:element` CALLBACK RUNS LAST, so the node it is handed is whole: a child
|
|
564
|
+
// component, an arm or a list inside it has built, and `form.querySelector('input')` finds an
|
|
565
|
+
// `<input>` an `<Input>` makes.
|
|
564
566
|
// 32.67 — A ROW'S ITEM WATCHES FIRST, one after another, which is how its scope finds them
|
|
565
567
|
// (`Scope.itemWatch`).
|
|
566
568
|
const items: string[] = []
|
|
@@ -597,7 +599,6 @@ function emitRegion(sink: Cursor, region: RegionEmission): RegionEmission {
|
|
|
597
599
|
for (const unit of texts) lines.push(unit)
|
|
598
600
|
for (const unit of handlers) lines.push(unit)
|
|
599
601
|
for (const unit of attributes) lines.push(unit)
|
|
600
|
-
for (const unit of elements) lines.push(unit)
|
|
601
602
|
|
|
602
603
|
// 32.67 — WHAT A ROW'S REGIONS AND COMPONENTS BIND reads the row's item through its cell: the
|
|
603
604
|
// row's `update` reaches its own top level and no further.
|
|
@@ -613,6 +614,7 @@ function emitRegion(sink: Cursor, region: RegionEmission): RegionEmission {
|
|
|
613
614
|
else emitInvocation(at, holder, region)
|
|
614
615
|
}
|
|
615
616
|
}
|
|
617
|
+
for (const unit of elements) lines.push(unit)
|
|
616
618
|
// 32.43 — A REGION THAT MOUNTS NOTHING INVOKES NOTHING, so what it declares is reached
|
|
617
619
|
// from nowhere and is not declared: a row declaring a component it never invokes stays a
|
|
618
620
|
// row whose mount is the shared empty one.
|
|
@@ -31,7 +31,7 @@ export function invocationProps(
|
|
|
31
31
|
const key = propKeyOf(attribute)
|
|
32
32
|
if (key === undefined)
|
|
33
33
|
throw new Error(
|
|
34
|
-
`abide: ${attribute.name} on <${node.tag}> is not a prop a component takes — \`bind:\` hands over the \`Reactive\` in its braces (RULEBOOK 32.6),
|
|
34
|
+
`abide: ${attribute.name} on <${node.tag}> is not a prop a component takes — \`bind:\` hands over the \`Reactive\` in its braces (RULEBOOK 32.6), \`class:\` and \`style:\` set an element's own class and style (RULEBOOK 32.10), and \`bind:element\` hands over an element — put it on one inside <${node.tag}>, or pass the callback as a prop (RULEBOOK 32.69).`,
|
|
35
35
|
)
|
|
36
36
|
// A STATIC PROP IS STILL AN ACCESSOR. One shape per prop whatever the call site spelled
|
|
37
37
|
// (33.10), so the child reads every key the same way and a literal is not a second case.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// The `abide-bridge` release a pairing command names, so a visitor's `bunx` runs the relay this
|
|
2
2
|
// server speaks. `packages/abide/tests/claudeCode.test.ts` holds it to the bridge package's own.
|
|
3
|
-
export const BRIDGE_VERSION = '0.
|
|
3
|
+
export const BRIDGE_VERSION = '0.3.0'
|
package/src/server/assistant.ts
CHANGED
|
@@ -20,7 +20,8 @@ export type AssistantMessage = { role: 'user' | 'assistant'; content: string }
|
|
|
20
20
|
/** What a conversation yields, the same from every provider. */
|
|
21
21
|
export type AssistantEvent =
|
|
22
22
|
| { type: 'text'; text: string }
|
|
23
|
-
| { type: 'tool'; id: string; name: string
|
|
23
|
+
| { type: 'tool'; id: string; name: string }
|
|
24
|
+
| { type: 'input'; id: string; input: unknown }
|
|
24
25
|
| { type: 'result'; id: string; text: string; failed: boolean }
|
|
25
26
|
| {
|
|
26
27
|
type: 'done'
|
package/src/server/claudeApi.ts
CHANGED
|
@@ -118,10 +118,19 @@ export function claudeApi(config: ClaudeApiConfig): Provider {
|
|
|
118
118
|
case 'message_start':
|
|
119
119
|
usage.input += inputOf(event.message.usage)
|
|
120
120
|
break
|
|
121
|
-
case 'content_block_start':
|
|
122
|
-
|
|
121
|
+
case 'content_block_start': {
|
|
122
|
+
const block = event.content_block
|
|
123
|
+
blocks[event.index] = block
|
|
123
124
|
partials[event.index] = ''
|
|
125
|
+
// 44.29 — announced as the model starts writing it.
|
|
126
|
+
if (block.type === 'tool_use')
|
|
127
|
+
yield {
|
|
128
|
+
type: 'tool',
|
|
129
|
+
id: block.id as string,
|
|
130
|
+
name: block.name as string,
|
|
131
|
+
}
|
|
124
132
|
break
|
|
133
|
+
}
|
|
125
134
|
case 'content_block_delta': {
|
|
126
135
|
const block = blocks[event.index] as Block
|
|
127
136
|
const delta = event.delta
|
|
@@ -152,9 +161,8 @@ export function claudeApi(config: ClaudeApiConfig): Provider {
|
|
|
152
161
|
}
|
|
153
162
|
called.push(block)
|
|
154
163
|
yield {
|
|
155
|
-
type: '
|
|
164
|
+
type: 'input',
|
|
156
165
|
id: block.id as string,
|
|
157
|
-
name: block.name as string,
|
|
158
166
|
input: block.input,
|
|
159
167
|
}
|
|
160
168
|
break
|
package/src/server/claudeCode.ts
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
// turn and answer the MCP requests it makes from the `Toolbox` — in this request's scope, as this
|
|
4
4
|
// asker (44.7) — so its tools are the site's and nothing of the visitor's machine is one.
|
|
5
5
|
//
|
|
6
|
-
// CONFIGURED BY CLAUDE CODE'S OWN OPTION NAMES,
|
|
7
|
-
// a site power over the visitor's machine —
|
|
8
|
-
// option here at all
|
|
6
|
+
// CONFIGURED BY CLAUDE CODE'S OWN OPTION NAMES, which the bridge lays on as their flags, and only the ones
|
|
7
|
+
// that shape the answer. What would give a site power over the visitor's machine — permissions,
|
|
8
|
+
// directory, settings — is not an option here at all, and its built-in `tools` are a request the visitor
|
|
9
|
+
// grants or does not: the bridge decides (44.15, 44.16, 44.30).
|
|
9
10
|
|
|
10
11
|
import { mounted } from '#shared/mount.ts'
|
|
11
12
|
import { refuse } from '#shared/refuse.ts'
|
|
@@ -28,13 +29,17 @@ import { mcpFailure } from './generatedSurfaces.ts'
|
|
|
28
29
|
import { Inbox } from './Inbox.ts'
|
|
29
30
|
import { request } from './requestScope.ts'
|
|
30
31
|
|
|
31
|
-
/** The Claude Code options a site may set for a turn. */
|
|
32
|
+
/** The Claude Code options a site may set for a turn, and the built-in tools it asks the visitor for. */
|
|
32
33
|
export type ClaudeCodeConfig = {
|
|
33
34
|
model?: string
|
|
34
35
|
fallbackModel?: string
|
|
35
36
|
systemPrompt?: string
|
|
36
37
|
appendSystemPrompt?: string
|
|
37
38
|
effort?: 'low' | 'medium' | 'high' | 'xhigh' | 'max'
|
|
39
|
+
maxBudgetUsd?: number
|
|
40
|
+
betas?: string[]
|
|
41
|
+
disallowedTools?: string[]
|
|
42
|
+
tools?: string[]
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
/** Whether this browser's bridge is connected, and the command that pairs one where it is not. */
|
package/src/ui/bindElement.ts
CHANGED
|
@@ -21,6 +21,10 @@ import { holdWhileLeaving } from './leave.ts'
|
|
|
21
21
|
* form is where teardown is decided, and its `Disposer` is the whole of it.
|
|
22
22
|
*
|
|
23
23
|
* 32.38 — A `Disposer` HANDING BACK A THENABLE IS AN EXIT: the element's nodes stay until it settles.
|
|
24
|
+
*
|
|
25
|
+
* 32.68 — THE NODE IS CONNECTED AND WHOLE, and nothing here makes it so: this runs from a region's
|
|
26
|
+
* MOUNT, which every caller (`ArmRegion`, `TryRegion`, `makeRow`) calls after `build`'s nodes are
|
|
27
|
+
* inserted, and last in it, after the blocks and components inside the node (`emitRegion`).
|
|
24
28
|
*/
|
|
25
29
|
export function bindElement(
|
|
26
30
|
element: Element,
|