@emblemvault/hustle-react 1.4.2 → 1.4.4

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.
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { C as ChatMessage, T as ToolCall } from '../hustle-S48t4lTZ.cjs';
2
+ import { C as ChatMessage, T as ToolCall } from '../hustle-C0Ltl5k4.cjs';
3
3
  import React from 'react';
4
4
  import 'hustle-incognito';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { C as ChatMessage, T as ToolCall } from '../hustle-S48t4lTZ.js';
2
+ import { C as ChatMessage, T as ToolCall } from '../hustle-C0Ltl5k4.js';
3
3
  import React from 'react';
4
4
  import 'hustle-incognito';
5
5
 
@@ -1751,6 +1751,15 @@ Executors run in the browser context with full access to:
1751
1751
  - **window.__hustleListPlugins()** - List all installed plugins
1752
1752
  - **window.__hustleGetPlugin(name)** - Get a specific plugin by name
1753
1753
 
1754
+ ### Hustle Settings Globals (Read/Write)
1755
+ - **window.__hustleGetModel()** - Get the current model override (empty string = server default)
1756
+ - **window.__hustleSetModel(model)** - Set the model override (e.g., "anthropic/claude-3-opus")
1757
+ - **window.__hustleGetSystemPrompt()** - Get the current system prompt override
1758
+ - **window.__hustleSetSystemPrompt(prompt)** - Set the system prompt override
1759
+ - **window.__hustleGetSkipServerPrompt()** - Get whether server prompt is skipped (boolean)
1760
+ - **window.__hustleSetSkipServerPrompt(skip)** - Set whether to skip server prompt
1761
+ - **window.__hustleGetModels()** - Get list of available models (read-only)
1762
+
1754
1763
  ### DOM Manipulation Examples
1755
1764
  Create a modal: document.createElement('div'), style it, append to document.body
1756
1765
  Add event listeners: element.addEventListener('click', handler)
@@ -3597,7 +3606,14 @@ function HustleChat({
3597
3606
  setIsStreaming(true);
3598
3607
  setCurrentToolCalls([]);
3599
3608
  try {
3600
- const chatMessages = messagesRef.current.filter((m) => !m.isStreaming).map((m) => ({ role: m.role, content: m.content }));
3609
+ const chatMessages = messagesRef.current.filter((m) => !m.isStreaming).map((m) => {
3610
+ const msg = { role: m.role, content: m.content };
3611
+ if (m.role === "assistant" && m.toolInvocations && m.toolInvocations.length > 0) {
3612
+ msg.toolInvocations = m.toolInvocations;
3613
+ msg.parts = m.parts;
3614
+ }
3615
+ return msg;
3616
+ });
3601
3617
  chatMessages.push({ role: "user", content: "continue" });
3602
3618
  const stream = chatStream({
3603
3619
  messages: chatMessages,
@@ -3605,6 +3621,9 @@ function HustleChat({
3605
3621
  });
3606
3622
  let fullContent = "";
3607
3623
  const toolCallsAccumulated = [];
3624
+ const toolInvocationsAccumulated = [];
3625
+ const partsAccumulated = [{ type: "step-start" }];
3626
+ let stepCounter = 0;
3608
3627
  for await (const chunk of stream) {
3609
3628
  if (chunk.type === "text") {
3610
3629
  fullContent += chunk.value;
@@ -3616,22 +3635,79 @@ function HustleChat({
3616
3635
  } else if (chunk.type === "tool_call") {
3617
3636
  const toolCall = chunk.value;
3618
3637
  toolCallsAccumulated.push(toolCall);
3638
+ const invocation = {
3639
+ state: "call",
3640
+ step: stepCounter++,
3641
+ toolCallId: toolCall.toolCallId,
3642
+ toolName: toolCall.toolName,
3643
+ args: toolCall.args
3644
+ };
3645
+ toolInvocationsAccumulated.push(invocation);
3646
+ partsAccumulated.push({ type: "tool-invocation", toolInvocation: invocation });
3619
3647
  setCurrentToolCalls([...toolCallsAccumulated]);
3620
3648
  setMessages(
3621
3649
  (prev) => prev.map(
3622
- (m) => m.id === assistantMessage.id ? { ...m, toolCalls: [...toolCallsAccumulated] } : m
3650
+ (m) => m.id === assistantMessage.id ? {
3651
+ ...m,
3652
+ toolCalls: [...toolCallsAccumulated],
3653
+ toolInvocations: [...toolInvocationsAccumulated],
3654
+ parts: [...partsAccumulated]
3655
+ } : m
3623
3656
  )
3624
3657
  );
3625
3658
  onToolCall?.(toolCall);
3659
+ } else if (chunk.type === "tool_result") {
3660
+ const toolResult = chunk.value;
3661
+ const invocationIndex = toolInvocationsAccumulated.findIndex(
3662
+ (inv) => inv.toolCallId === toolResult.toolCallId
3663
+ );
3664
+ if (invocationIndex !== -1) {
3665
+ toolInvocationsAccumulated[invocationIndex] = {
3666
+ ...toolInvocationsAccumulated[invocationIndex],
3667
+ state: "result",
3668
+ result: toolResult.result
3669
+ };
3670
+ const partIndex = partsAccumulated.findIndex(
3671
+ (p) => p.type === "tool-invocation" && p.toolInvocation.toolCallId === toolResult.toolCallId
3672
+ );
3673
+ if (partIndex !== -1) {
3674
+ partsAccumulated[partIndex] = {
3675
+ type: "tool-invocation",
3676
+ toolInvocation: toolInvocationsAccumulated[invocationIndex]
3677
+ };
3678
+ }
3679
+ }
3680
+ setMessages(
3681
+ (prev) => prev.map(
3682
+ (m) => m.id === assistantMessage.id ? {
3683
+ ...m,
3684
+ toolInvocations: [...toolInvocationsAccumulated],
3685
+ parts: [...partsAccumulated]
3686
+ } : m
3687
+ )
3688
+ );
3626
3689
  } else if (chunk.type === "error") {
3627
3690
  console.error("Stream error:", chunk.value);
3628
3691
  }
3629
3692
  }
3630
3693
  const processedResponse = await stream.response;
3631
3694
  const finalContent = processedResponse?.content || fullContent || "(No response)";
3695
+ const finalParts = [{ type: "step-start" }];
3696
+ if (finalContent) {
3697
+ finalParts.push({ type: "text", text: finalContent });
3698
+ }
3699
+ for (const inv of toolInvocationsAccumulated) {
3700
+ finalParts.push({ type: "tool-invocation", toolInvocation: inv });
3701
+ }
3632
3702
  setMessages(
3633
3703
  (prev) => prev.map(
3634
- (m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: finalContent } : m
3704
+ (m) => m.id === assistantMessage.id ? {
3705
+ ...m,
3706
+ isStreaming: false,
3707
+ content: finalContent,
3708
+ toolInvocations: toolInvocationsAccumulated.length > 0 ? toolInvocationsAccumulated : void 0,
3709
+ parts: toolInvocationsAccumulated.length > 0 ? finalParts : void 0
3710
+ } : m
3635
3711
  )
3636
3712
  );
3637
3713
  onResponse?.(finalContent);
@@ -3693,7 +3769,14 @@ function HustleChat({
3693
3769
  setIsStreaming(true);
3694
3770
  setCurrentToolCalls([]);
3695
3771
  try {
3696
- const chatMessages = messages.filter((m) => !m.isStreaming).map((m) => ({ role: m.role, content: m.content }));
3772
+ const chatMessages = messages.filter((m) => !m.isStreaming).map((m) => {
3773
+ const msg = { role: m.role, content: m.content };
3774
+ if (m.role === "assistant" && m.toolInvocations && m.toolInvocations.length > 0) {
3775
+ msg.toolInvocations = m.toolInvocations;
3776
+ msg.parts = m.parts;
3777
+ }
3778
+ return msg;
3779
+ });
3697
3780
  chatMessages.push({ role: "user", content });
3698
3781
  const stream = chatStream({
3699
3782
  messages: chatMessages,
@@ -3703,6 +3786,9 @@ function HustleChat({
3703
3786
  setAttachments([]);
3704
3787
  let fullContent = "";
3705
3788
  const toolCallsAccumulated = [];
3789
+ const toolInvocationsAccumulated = [];
3790
+ const partsAccumulated = [{ type: "step-start" }];
3791
+ let stepCounter = 0;
3706
3792
  for await (const chunk of stream) {
3707
3793
  if (chunk.type === "text") {
3708
3794
  fullContent += chunk.value;
@@ -3714,22 +3800,79 @@ function HustleChat({
3714
3800
  } else if (chunk.type === "tool_call") {
3715
3801
  const toolCall = chunk.value;
3716
3802
  toolCallsAccumulated.push(toolCall);
3803
+ const invocation = {
3804
+ state: "call",
3805
+ step: stepCounter++,
3806
+ toolCallId: toolCall.toolCallId,
3807
+ toolName: toolCall.toolName,
3808
+ args: toolCall.args
3809
+ };
3810
+ toolInvocationsAccumulated.push(invocation);
3811
+ partsAccumulated.push({ type: "tool-invocation", toolInvocation: invocation });
3717
3812
  setCurrentToolCalls([...toolCallsAccumulated]);
3718
3813
  setMessages(
3719
3814
  (prev) => prev.map(
3720
- (m) => m.id === assistantMessage.id ? { ...m, toolCalls: [...toolCallsAccumulated] } : m
3815
+ (m) => m.id === assistantMessage.id ? {
3816
+ ...m,
3817
+ toolCalls: [...toolCallsAccumulated],
3818
+ toolInvocations: [...toolInvocationsAccumulated],
3819
+ parts: [...partsAccumulated]
3820
+ } : m
3721
3821
  )
3722
3822
  );
3723
3823
  onToolCall?.(toolCall);
3824
+ } else if (chunk.type === "tool_result") {
3825
+ const toolResult = chunk.value;
3826
+ const invocationIndex = toolInvocationsAccumulated.findIndex(
3827
+ (inv) => inv.toolCallId === toolResult.toolCallId
3828
+ );
3829
+ if (invocationIndex !== -1) {
3830
+ toolInvocationsAccumulated[invocationIndex] = {
3831
+ ...toolInvocationsAccumulated[invocationIndex],
3832
+ state: "result",
3833
+ result: toolResult.result
3834
+ };
3835
+ const partIndex = partsAccumulated.findIndex(
3836
+ (p) => p.type === "tool-invocation" && p.toolInvocation.toolCallId === toolResult.toolCallId
3837
+ );
3838
+ if (partIndex !== -1) {
3839
+ partsAccumulated[partIndex] = {
3840
+ type: "tool-invocation",
3841
+ toolInvocation: toolInvocationsAccumulated[invocationIndex]
3842
+ };
3843
+ }
3844
+ }
3845
+ setMessages(
3846
+ (prev) => prev.map(
3847
+ (m) => m.id === assistantMessage.id ? {
3848
+ ...m,
3849
+ toolInvocations: [...toolInvocationsAccumulated],
3850
+ parts: [...partsAccumulated]
3851
+ } : m
3852
+ )
3853
+ );
3724
3854
  } else if (chunk.type === "error") {
3725
3855
  console.error("Stream error:", chunk.value);
3726
3856
  }
3727
3857
  }
3728
3858
  const processedResponse = await stream.response;
3729
3859
  const finalContent = processedResponse?.content || fullContent || "(No response)";
3860
+ const finalParts = [{ type: "step-start" }];
3861
+ if (finalContent) {
3862
+ finalParts.push({ type: "text", text: finalContent });
3863
+ }
3864
+ for (const inv of toolInvocationsAccumulated) {
3865
+ finalParts.push({ type: "tool-invocation", toolInvocation: inv });
3866
+ }
3730
3867
  setMessages(
3731
3868
  (prev) => prev.map(
3732
- (m) => m.id === assistantMessage.id ? { ...m, isStreaming: false, content: finalContent } : m
3869
+ (m) => m.id === assistantMessage.id ? {
3870
+ ...m,
3871
+ isStreaming: false,
3872
+ content: finalContent,
3873
+ toolInvocations: toolInvocationsAccumulated.length > 0 ? toolInvocationsAccumulated : void 0,
3874
+ parts: toolInvocationsAccumulated.length > 0 ? finalParts : void 0
3875
+ } : m
3733
3876
  )
3734
3877
  );
3735
3878
  onResponse?.(finalContent);