@tambo-ai/react 0.74.0 → 0.75.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/README.md +46 -449
- package/dist/hoc/with-tambo-interactable.d.ts +8 -0
- package/dist/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/dist/hoc/with-tambo-interactable.js +5 -2
- package/dist/hoc/with-tambo-interactable.js.map +1 -1
- package/dist/hoc/with-tambo-interactable.test.js +12 -0
- package/dist/hoc/with-tambo-interactable.test.js.map +1 -1
- package/dist/hooks/use-tambo-voice.test.js +3 -0
- package/dist/hooks/use-tambo-voice.test.js.map +1 -1
- package/dist/mcp/mcp-hooks.d.ts.map +1 -1
- package/dist/mcp/mcp-hooks.js +70 -16
- package/dist/mcp/mcp-hooks.js.map +1 -1
- package/dist/mcp/mcp-hooks.test.js +69 -0
- package/dist/mcp/mcp-hooks.test.js.map +1 -1
- package/dist/mcp/tambo-mcp-provider.test.js +24 -0
- package/dist/mcp/tambo-mcp-provider.test.js.map +1 -1
- package/dist/mcp/use-mcp-servers.test.js +9 -0
- package/dist/mcp/use-mcp-servers.test.js.map +1 -1
- package/dist/model/component-metadata.d.ts +4 -4
- package/dist/model/component-metadata.js.map +1 -1
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js +2 -2
- package/dist/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -1
- package/dist/providers/tambo-client-provider.d.ts +6 -0
- package/dist/providers/tambo-client-provider.d.ts.map +1 -1
- package/dist/providers/tambo-client-provider.js +4 -1
- package/dist/providers/tambo-client-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/dist/providers/tambo-interactable-provider.js +8 -0
- package/dist/providers/tambo-interactable-provider.js.map +1 -1
- package/dist/providers/tambo-interactable-provider.test.js +47 -0
- package/dist/providers/tambo-interactable-provider.test.js.map +1 -1
- package/dist/providers/tambo-provider.d.ts.map +1 -1
- package/dist/providers/tambo-provider.js +4 -1
- package/dist/providers/tambo-provider.js.map +1 -1
- package/dist/providers/tambo-stubs.d.ts.map +1 -1
- package/dist/providers/tambo-stubs.js +3 -0
- package/dist/providers/tambo-stubs.js.map +1 -1
- package/dist/providers/tambo-thread-provider-initial-messages.test.js +3 -0
- package/dist/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/dist/providers/tambo-thread-provider.test.js +3 -0
- package/dist/providers/tambo-thread-provider.test.js.map +1 -1
- package/dist/util/registry-validators.js +1 -1
- package/dist/util/registry-validators.js.map +1 -1
- package/dist/util/resource-content-resolver.test.js +1 -1
- package/dist/util/resource-content-resolver.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts +11 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.js +48 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.d.ts +2 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.d.ts.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js +105 -0
- package/dist/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -0
- package/dist/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.js +68 -21
- package/dist/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js +100 -0
- package/dist/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-messages.test.js +8 -0
- package/dist/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts +19 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.js +86 -9
- package/dist/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js +273 -0
- package/dist/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts +2 -2
- package/dist/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.js +2 -2
- package/dist/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js +11 -11
- package/dist/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js +13 -0
- package/dist/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.js +4 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js +6 -0
- package/dist/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.js +4 -0
- package/dist/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1-thread.test.js +6 -0
- package/dist/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.d.ts +11 -0
- package/dist/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.js +5 -0
- package/dist/v1/hooks/use-tambo-v1.js.map +1 -1
- package/dist/v1/hooks/use-tambo-v1.test.js +13 -0
- package/dist/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/dist/v1/index.d.ts +4 -1
- package/dist/v1/index.d.ts.map +1 -1
- package/dist/v1/index.js +5 -2
- package/dist/v1/index.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts +16 -1
- package/dist/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.js +42 -5
- package/dist/v1/providers/tambo-v1-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-provider.test.js +19 -2
- package/dist/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.d.ts +6 -0
- package/dist/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.js +50 -11
- package/dist/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stream-context.test.js +9 -0
- package/dist/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-stub-provider.js +4 -0
- package/dist/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts +11 -0
- package/dist/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.js +10 -1
- package/dist/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/dist/v1/types/auth.d.ts +24 -0
- package/dist/v1/types/auth.d.ts.map +1 -0
- package/dist/v1/types/auth.js +3 -0
- package/dist/v1/types/auth.js.map +1 -0
- package/dist/v1/types/message.d.ts +12 -0
- package/dist/v1/types/message.d.ts.map +1 -1
- package/dist/v1/types/message.js.map +1 -1
- package/dist/v1/types/tool-choice.d.ts +8 -0
- package/dist/v1/types/tool-choice.d.ts.map +1 -0
- package/dist/v1/types/tool-choice.js +3 -0
- package/dist/v1/types/tool-choice.js.map +1 -0
- package/dist/v1/utils/event-accumulator.d.ts +28 -2
- package/dist/v1/utils/event-accumulator.d.ts.map +1 -1
- package/dist/v1/utils/event-accumulator.js +67 -15
- package/dist/v1/utils/event-accumulator.js.map +1 -1
- package/dist/v1/utils/event-accumulator.test.js +106 -0
- package/dist/v1/utils/event-accumulator.test.js.map +1 -1
- package/dist/v1/utils/keyed-throttle.d.ts +42 -0
- package/dist/v1/utils/keyed-throttle.d.ts.map +1 -0
- package/dist/v1/utils/keyed-throttle.js +86 -0
- package/dist/v1/utils/keyed-throttle.js.map +1 -0
- package/dist/v1/utils/keyed-throttle.test.d.ts +2 -0
- package/dist/v1/utils/keyed-throttle.test.d.ts.map +1 -0
- package/dist/v1/utils/keyed-throttle.test.js +147 -0
- package/dist/v1/utils/keyed-throttle.test.js.map +1 -0
- package/dist/v1/utils/registry-conversion.d.ts.map +1 -1
- package/dist/v1/utils/registry-conversion.js +2 -0
- package/dist/v1/utils/registry-conversion.js.map +1 -1
- package/dist/v1/utils/registry-conversion.test.js +23 -0
- package/dist/v1/utils/registry-conversion.test.js.map +1 -1
- package/dist/v1/utils/tool-call-tracker.d.ts +10 -0
- package/dist/v1/utils/tool-call-tracker.d.ts.map +1 -1
- package/dist/v1/utils/tool-call-tracker.js +13 -0
- package/dist/v1/utils/tool-call-tracker.js.map +1 -1
- package/dist/v1/utils/tool-call-tracker.test.d.ts +2 -0
- package/dist/v1/utils/tool-call-tracker.test.d.ts.map +1 -0
- package/dist/v1/utils/tool-call-tracker.test.js +67 -0
- package/dist/v1/utils/tool-call-tracker.test.js.map +1 -0
- package/dist/v1/utils/tool-executor.d.ts +34 -0
- package/dist/v1/utils/tool-executor.d.ts.map +1 -1
- package/dist/v1/utils/tool-executor.js +55 -0
- package/dist/v1/utils/tool-executor.js.map +1 -1
- package/dist/v1/utils/tool-executor.test.js +211 -0
- package/dist/v1/utils/tool-executor.test.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.d.ts +8 -0
- package/esm/hoc/with-tambo-interactable.d.ts.map +1 -1
- package/esm/hoc/with-tambo-interactable.js +5 -2
- package/esm/hoc/with-tambo-interactable.js.map +1 -1
- package/esm/hoc/with-tambo-interactable.test.js +12 -0
- package/esm/hoc/with-tambo-interactable.test.js.map +1 -1
- package/esm/hooks/use-tambo-voice.test.js +3 -0
- package/esm/hooks/use-tambo-voice.test.js.map +1 -1
- package/esm/mcp/mcp-hooks.d.ts.map +1 -1
- package/esm/mcp/mcp-hooks.js +70 -16
- package/esm/mcp/mcp-hooks.js.map +1 -1
- package/esm/mcp/mcp-hooks.test.js +69 -0
- package/esm/mcp/mcp-hooks.test.js.map +1 -1
- package/esm/mcp/tambo-mcp-provider.test.js +24 -0
- package/esm/mcp/tambo-mcp-provider.test.js.map +1 -1
- package/esm/mcp/use-mcp-servers.test.js +9 -0
- package/esm/mcp/use-mcp-servers.test.js.map +1 -1
- package/esm/model/component-metadata.d.ts +4 -4
- package/esm/model/component-metadata.js.map +1 -1
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js +2 -2
- package/esm/providers/__tests__/thread-input-resource-resolution.test.js.map +1 -1
- package/esm/providers/tambo-client-provider.d.ts +6 -0
- package/esm/providers/tambo-client-provider.d.ts.map +1 -1
- package/esm/providers/tambo-client-provider.js +4 -1
- package/esm/providers/tambo-client-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.d.ts.map +1 -1
- package/esm/providers/tambo-interactable-provider.js +8 -0
- package/esm/providers/tambo-interactable-provider.js.map +1 -1
- package/esm/providers/tambo-interactable-provider.test.js +47 -0
- package/esm/providers/tambo-interactable-provider.test.js.map +1 -1
- package/esm/providers/tambo-provider.d.ts.map +1 -1
- package/esm/providers/tambo-provider.js +4 -1
- package/esm/providers/tambo-provider.js.map +1 -1
- package/esm/providers/tambo-stubs.d.ts.map +1 -1
- package/esm/providers/tambo-stubs.js +3 -0
- package/esm/providers/tambo-stubs.js.map +1 -1
- package/esm/providers/tambo-thread-provider-initial-messages.test.js +3 -0
- package/esm/providers/tambo-thread-provider-initial-messages.test.js.map +1 -1
- package/esm/providers/tambo-thread-provider.test.js +3 -0
- package/esm/providers/tambo-thread-provider.test.js.map +1 -1
- package/esm/util/registry-validators.js +1 -1
- package/esm/util/registry-validators.js.map +1 -1
- package/esm/util/resource-content-resolver.test.js +1 -1
- package/esm/util/resource-content-resolver.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts +11 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.js +45 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.d.ts +2 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.d.ts.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js +100 -0
- package/esm/v1/hooks/use-tambo-v1-auth-state.test.js.map +1 -0
- package/esm/v1/hooks/use-tambo-v1-component-state.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.js +68 -21
- package/esm/v1/hooks/use-tambo-v1-component-state.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js +100 -0
- package/esm/v1/hooks/use-tambo-v1-component-state.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-messages.test.js +8 -0
- package/esm/v1/hooks/use-tambo-v1-messages.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts +19 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.js +87 -10
- package/esm/v1/hooks/use-tambo-v1-send-message.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js +273 -0
- package/esm/v1/hooks/use-tambo-v1-send-message.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts +2 -2
- package/esm/v1/hooks/use-tambo-v1-stream-status.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.js +2 -2
- package/esm/v1/hooks/use-tambo-v1-stream-status.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js +11 -11
- package/esm/v1/hooks/use-tambo-v1-stream-status.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js +13 -0
- package/esm/v1/hooks/use-tambo-v1-thread-input.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.js +4 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js +6 -0
- package/esm/v1/hooks/use-tambo-v1-thread-list.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.js +4 -0
- package/esm/v1/hooks/use-tambo-v1-thread.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1-thread.test.js +6 -0
- package/esm/v1/hooks/use-tambo-v1-thread.test.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.d.ts +11 -0
- package/esm/v1/hooks/use-tambo-v1.d.ts.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.js +5 -0
- package/esm/v1/hooks/use-tambo-v1.js.map +1 -1
- package/esm/v1/hooks/use-tambo-v1.test.js +13 -0
- package/esm/v1/hooks/use-tambo-v1.test.js.map +1 -1
- package/esm/v1/index.d.ts +4 -1
- package/esm/v1/index.d.ts.map +1 -1
- package/esm/v1/index.js +3 -1
- package/esm/v1/index.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts +16 -1
- package/esm/v1/providers/tambo-v1-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.js +43 -6
- package/esm/v1/providers/tambo-v1-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-provider.test.js +19 -2
- package/esm/v1/providers/tambo-v1-provider.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.d.ts +6 -0
- package/esm/v1/providers/tambo-v1-stream-context.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.js +51 -12
- package/esm/v1/providers/tambo-v1-stream-context.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stream-context.test.js +9 -0
- package/esm/v1/providers/tambo-v1-stream-context.test.js.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-stub-provider.js +4 -0
- package/esm/v1/providers/tambo-v1-stub-provider.js.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts +11 -0
- package/esm/v1/providers/tambo-v1-thread-input-provider.d.ts.map +1 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.js +10 -1
- package/esm/v1/providers/tambo-v1-thread-input-provider.js.map +1 -1
- package/esm/v1/types/auth.d.ts +24 -0
- package/esm/v1/types/auth.d.ts.map +1 -0
- package/esm/v1/types/auth.js +2 -0
- package/esm/v1/types/auth.js.map +1 -0
- package/esm/v1/types/message.d.ts +12 -0
- package/esm/v1/types/message.d.ts.map +1 -1
- package/esm/v1/types/message.js.map +1 -1
- package/esm/v1/types/tool-choice.d.ts +8 -0
- package/esm/v1/types/tool-choice.d.ts.map +1 -0
- package/esm/v1/types/tool-choice.js +2 -0
- package/esm/v1/types/tool-choice.js.map +1 -0
- package/esm/v1/utils/event-accumulator.d.ts +28 -2
- package/esm/v1/utils/event-accumulator.d.ts.map +1 -1
- package/esm/v1/utils/event-accumulator.js +66 -15
- package/esm/v1/utils/event-accumulator.js.map +1 -1
- package/esm/v1/utils/event-accumulator.test.js +106 -0
- package/esm/v1/utils/event-accumulator.test.js.map +1 -1
- package/esm/v1/utils/keyed-throttle.d.ts +42 -0
- package/esm/v1/utils/keyed-throttle.d.ts.map +1 -0
- package/esm/v1/utils/keyed-throttle.js +83 -0
- package/esm/v1/utils/keyed-throttle.js.map +1 -0
- package/esm/v1/utils/keyed-throttle.test.d.ts +2 -0
- package/esm/v1/utils/keyed-throttle.test.d.ts.map +1 -0
- package/esm/v1/utils/keyed-throttle.test.js +145 -0
- package/esm/v1/utils/keyed-throttle.test.js.map +1 -0
- package/esm/v1/utils/registry-conversion.d.ts.map +1 -1
- package/esm/v1/utils/registry-conversion.js +2 -0
- package/esm/v1/utils/registry-conversion.js.map +1 -1
- package/esm/v1/utils/registry-conversion.test.js +23 -0
- package/esm/v1/utils/registry-conversion.test.js.map +1 -1
- package/esm/v1/utils/tool-call-tracker.d.ts +10 -0
- package/esm/v1/utils/tool-call-tracker.d.ts.map +1 -1
- package/esm/v1/utils/tool-call-tracker.js +13 -0
- package/esm/v1/utils/tool-call-tracker.js.map +1 -1
- package/esm/v1/utils/tool-call-tracker.test.d.ts +2 -0
- package/esm/v1/utils/tool-call-tracker.test.d.ts.map +1 -0
- package/esm/v1/utils/tool-call-tracker.test.js +65 -0
- package/esm/v1/utils/tool-call-tracker.test.js.map +1 -0
- package/esm/v1/utils/tool-executor.d.ts +34 -0
- package/esm/v1/utils/tool-executor.d.ts.map +1 -1
- package/esm/v1/utils/tool-executor.js +53 -0
- package/esm/v1/utils/tool-executor.js.map +1 -1
- package/esm/v1/utils/tool-executor.test.js +212 -1
- package/esm/v1/utils/tool-executor.test.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyed Throttle Utility
|
|
3
|
+
*
|
|
4
|
+
* A generic leading+trailing throttle that maintains independent timers per
|
|
5
|
+
* string key. Fires immediately on the first call for a key, then at most
|
|
6
|
+
* once per `delay` ms while calls keep arriving, with a trailing fire to
|
|
7
|
+
* capture the final value.
|
|
8
|
+
*
|
|
9
|
+
* Useful when the same operation fires rapidly for multiple independent
|
|
10
|
+
* entities (e.g., multiple concurrent tool calls during streaming).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A throttle controller with independent timers per key.
|
|
14
|
+
*/
|
|
15
|
+
export interface KeyedThrottle<T> {
|
|
16
|
+
/** Schedule a throttled call for the given key. Fires immediately if idle, otherwise queues a trailing call. */
|
|
17
|
+
schedule(key: string, value: T): void;
|
|
18
|
+
/**
|
|
19
|
+
* Force-execute all pending trailing calls immediately, cancel all timers,
|
|
20
|
+
* and reset to idle. After flush(), the next schedule() for any key will
|
|
21
|
+
* fire immediately (leading edge) as if the key were new.
|
|
22
|
+
*/
|
|
23
|
+
flush(): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a keyed leading+trailing throttle.
|
|
27
|
+
*
|
|
28
|
+
* Each key gets its own independent throttle. On the first call for an idle
|
|
29
|
+
* key, `fn` fires immediately (leading edge). Subsequent calls during the
|
|
30
|
+
* cooldown window update the stored value. When the cooldown expires, if a
|
|
31
|
+
* new value arrived, `fn` fires again with the latest value (trailing edge)
|
|
32
|
+
* and the timer re-arms. This repeats until no new calls arrive during
|
|
33
|
+
* a cooldown window, at which point the key becomes idle.
|
|
34
|
+
*
|
|
35
|
+
* Call `flush()` to force-execute all pending trailing calls, cancel all
|
|
36
|
+
* timers, and reset to idle.
|
|
37
|
+
* @param fn - Callback invoked with (key, latestValue) on leading and trailing edges
|
|
38
|
+
* @param delay - Throttle interval in milliseconds
|
|
39
|
+
* @returns KeyedThrottle controller
|
|
40
|
+
*/
|
|
41
|
+
export declare function createKeyedThrottle<T>(fn: (key: string, value: T) => void, delay: number): KeyedThrottle<T>;
|
|
42
|
+
//# sourceMappingURL=keyed-throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyed-throttle.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/keyed-throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,gHAAgH;IAChH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;IACtC;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAaD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EACnC,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,EACnC,KAAK,EAAE,MAAM,GACZ,aAAa,CAAC,CAAC,CAAC,CA4DlB"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyed Throttle Utility
|
|
3
|
+
*
|
|
4
|
+
* A generic leading+trailing throttle that maintains independent timers per
|
|
5
|
+
* string key. Fires immediately on the first call for a key, then at most
|
|
6
|
+
* once per `delay` ms while calls keep arriving, with a trailing fire to
|
|
7
|
+
* capture the final value.
|
|
8
|
+
*
|
|
9
|
+
* Useful when the same operation fires rapidly for multiple independent
|
|
10
|
+
* entities (e.g., multiple concurrent tool calls during streaming).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Creates a keyed leading+trailing throttle.
|
|
14
|
+
*
|
|
15
|
+
* Each key gets its own independent throttle. On the first call for an idle
|
|
16
|
+
* key, `fn` fires immediately (leading edge). Subsequent calls during the
|
|
17
|
+
* cooldown window update the stored value. When the cooldown expires, if a
|
|
18
|
+
* new value arrived, `fn` fires again with the latest value (trailing edge)
|
|
19
|
+
* and the timer re-arms. This repeats until no new calls arrive during
|
|
20
|
+
* a cooldown window, at which point the key becomes idle.
|
|
21
|
+
*
|
|
22
|
+
* Call `flush()` to force-execute all pending trailing calls, cancel all
|
|
23
|
+
* timers, and reset to idle.
|
|
24
|
+
* @param fn - Callback invoked with (key, latestValue) on leading and trailing edges
|
|
25
|
+
* @param delay - Throttle interval in milliseconds
|
|
26
|
+
* @returns KeyedThrottle controller
|
|
27
|
+
*/
|
|
28
|
+
export function createKeyedThrottle(fn, delay) {
|
|
29
|
+
const pending = new Map();
|
|
30
|
+
function armTimer(key) {
|
|
31
|
+
const entry = pending.get(key);
|
|
32
|
+
if (!entry || entry.timer)
|
|
33
|
+
return;
|
|
34
|
+
const myGen = entry.gen;
|
|
35
|
+
entry.timer = setTimeout(() => {
|
|
36
|
+
const current = pending.get(key);
|
|
37
|
+
if (current?.gen !== myGen)
|
|
38
|
+
return;
|
|
39
|
+
current.timer = undefined;
|
|
40
|
+
if (!current.hasTrailing) {
|
|
41
|
+
// No new calls during cooldown — go idle
|
|
42
|
+
pending.delete(key);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Trailing fire with latest value
|
|
46
|
+
current.hasTrailing = false;
|
|
47
|
+
const trailingValue = current.latestValue;
|
|
48
|
+
fn(key, trailingValue);
|
|
49
|
+
// Re-arm only if more updates may arrive
|
|
50
|
+
armTimer(key);
|
|
51
|
+
}, delay);
|
|
52
|
+
}
|
|
53
|
+
function schedule(key, value) {
|
|
54
|
+
const existing = pending.get(key);
|
|
55
|
+
if (existing) {
|
|
56
|
+
// Currently in cooldown — update value, mark trailing
|
|
57
|
+
existing.latestValue = value;
|
|
58
|
+
existing.hasTrailing = true;
|
|
59
|
+
armTimer(key);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Idle — fire immediately (leading edge), start cooldown
|
|
63
|
+
fn(key, value);
|
|
64
|
+
pending.set(key, { latestValue: value, hasTrailing: false, gen: 0 });
|
|
65
|
+
armTimer(key);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function flush() {
|
|
69
|
+
for (const [key, entry] of pending) {
|
|
70
|
+
entry.gen++;
|
|
71
|
+
if (entry.timer) {
|
|
72
|
+
clearTimeout(entry.timer);
|
|
73
|
+
entry.timer = undefined;
|
|
74
|
+
}
|
|
75
|
+
if (entry.hasTrailing) {
|
|
76
|
+
fn(key, entry.latestValue);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
pending.clear();
|
|
80
|
+
}
|
|
81
|
+
return { schedule, flush };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=keyed-throttle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyed-throttle.js","sourceRoot":"","sources":["../../../src/v1/utils/keyed-throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA2BH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,mBAAmB,CACjC,EAAmC,EACnC,KAAa;IAEb,MAAM,OAAO,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEpD,SAAS,QAAQ,CAAC,GAAW;QAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK;YAAE,OAAO;QAElC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;QACxB,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,OAAO,EAAE,GAAG,KAAK,KAAK;gBAAE,OAAO;YAEnC,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC;YAE1B,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;gBACzB,yCAAyC;gBACzC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACpB,OAAO;YACT,CAAC;YAED,kCAAkC;YAClC,OAAO,CAAC,WAAW,GAAG,KAAK,CAAC;YAC5B,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;YAC1C,EAAE,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;YAEvB,yCAAyC;YACzC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IAED,SAAS,QAAQ,CAAC,GAAW,EAAE,KAAQ;QACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,QAAQ,EAAE,CAAC;YACb,sDAAsD;YACtD,QAAQ,CAAC,WAAW,GAAG,KAAK,CAAC;YAC7B,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC;YAC5B,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,yDAAyD;YACzD,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACrE,QAAQ,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IAED,SAAS,KAAK;QACZ,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;YACnC,KAAK,CAAC,GAAG,EAAE,CAAC;YACZ,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC1B,KAAK,CAAC,KAAK,GAAG,SAAS,CAAC;YAC1B,CAAC;YACD,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;gBACtB,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC","sourcesContent":["/**\n * Keyed Throttle Utility\n *\n * A generic leading+trailing throttle that maintains independent timers per\n * string key. Fires immediately on the first call for a key, then at most\n * once per `delay` ms while calls keep arriving, with a trailing fire to\n * capture the final value.\n *\n * Useful when the same operation fires rapidly for multiple independent\n * entities (e.g., multiple concurrent tool calls during streaming).\n */\n\n/**\n * A throttle controller with independent timers per key.\n */\nexport interface KeyedThrottle<T> {\n /** Schedule a throttled call for the given key. Fires immediately if idle, otherwise queues a trailing call. */\n schedule(key: string, value: T): void;\n /**\n * Force-execute all pending trailing calls immediately, cancel all timers,\n * and reset to idle. After flush(), the next schedule() for any key will\n * fire immediately (leading edge) as if the key were new.\n */\n flush(): void;\n}\n\ninterface ThrottleEntry<T> {\n /** Latest value received while throttled */\n latestValue: T;\n /** Whether a new value arrived during the cooldown window */\n hasTrailing: boolean;\n /** The active cooldown timer, if any */\n timer?: ReturnType<typeof setTimeout>;\n /** Generation counter — incremented on flush/reschedule to invalidate stale callbacks */\n gen: number;\n}\n\n/**\n * Creates a keyed leading+trailing throttle.\n *\n * Each key gets its own independent throttle. On the first call for an idle\n * key, `fn` fires immediately (leading edge). Subsequent calls during the\n * cooldown window update the stored value. When the cooldown expires, if a\n * new value arrived, `fn` fires again with the latest value (trailing edge)\n * and the timer re-arms. This repeats until no new calls arrive during\n * a cooldown window, at which point the key becomes idle.\n *\n * Call `flush()` to force-execute all pending trailing calls, cancel all\n * timers, and reset to idle.\n * @param fn - Callback invoked with (key, latestValue) on leading and trailing edges\n * @param delay - Throttle interval in milliseconds\n * @returns KeyedThrottle controller\n */\nexport function createKeyedThrottle<T>(\n fn: (key: string, value: T) => void,\n delay: number,\n): KeyedThrottle<T> {\n const pending = new Map<string, ThrottleEntry<T>>();\n\n function armTimer(key: string): void {\n const entry = pending.get(key);\n if (!entry || entry.timer) return;\n\n const myGen = entry.gen;\n entry.timer = setTimeout(() => {\n const current = pending.get(key);\n if (current?.gen !== myGen) return;\n\n current.timer = undefined;\n\n if (!current.hasTrailing) {\n // No new calls during cooldown — go idle\n pending.delete(key);\n return;\n }\n\n // Trailing fire with latest value\n current.hasTrailing = false;\n const trailingValue = current.latestValue;\n fn(key, trailingValue);\n\n // Re-arm only if more updates may arrive\n armTimer(key);\n }, delay);\n }\n\n function schedule(key: string, value: T): void {\n const existing = pending.get(key);\n if (existing) {\n // Currently in cooldown — update value, mark trailing\n existing.latestValue = value;\n existing.hasTrailing = true;\n armTimer(key);\n } else {\n // Idle — fire immediately (leading edge), start cooldown\n fn(key, value);\n pending.set(key, { latestValue: value, hasTrailing: false, gen: 0 });\n armTimer(key);\n }\n }\n\n function flush(): void {\n for (const [key, entry] of pending) {\n entry.gen++;\n if (entry.timer) {\n clearTimeout(entry.timer);\n entry.timer = undefined;\n }\n if (entry.hasTrailing) {\n fn(key, entry.latestValue);\n }\n }\n pending.clear();\n }\n\n return { schedule, flush };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyed-throttle.test.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/keyed-throttle.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { createKeyedThrottle } from "./keyed-throttle.js";
|
|
2
|
+
describe("createKeyedThrottle", () => {
|
|
3
|
+
beforeEach(() => {
|
|
4
|
+
jest.useFakeTimers();
|
|
5
|
+
});
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
jest.useRealTimers();
|
|
8
|
+
});
|
|
9
|
+
it("fires immediately on first call (leading edge)", () => {
|
|
10
|
+
const fn = jest.fn();
|
|
11
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
12
|
+
throttle.schedule("a", 1);
|
|
13
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
14
|
+
expect(fn).toHaveBeenCalledWith("a", 1);
|
|
15
|
+
});
|
|
16
|
+
it("does not fire again during cooldown window", () => {
|
|
17
|
+
const fn = jest.fn();
|
|
18
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
19
|
+
throttle.schedule("a", 1);
|
|
20
|
+
throttle.schedule("a", 2);
|
|
21
|
+
throttle.schedule("a", 3);
|
|
22
|
+
// Only the leading call should have fired
|
|
23
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
24
|
+
expect(fn).toHaveBeenCalledWith("a", 1);
|
|
25
|
+
});
|
|
26
|
+
it("fires trailing call with latest value after cooldown", () => {
|
|
27
|
+
const fn = jest.fn();
|
|
28
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
29
|
+
throttle.schedule("a", 1); // leading fire
|
|
30
|
+
throttle.schedule("a", 2);
|
|
31
|
+
throttle.schedule("a", 3);
|
|
32
|
+
jest.advanceTimersByTime(100);
|
|
33
|
+
// Trailing fire with latest value
|
|
34
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
35
|
+
expect(fn).toHaveBeenLastCalledWith("a", 3);
|
|
36
|
+
});
|
|
37
|
+
it("does not fire trailing call if no new values arrived", () => {
|
|
38
|
+
const fn = jest.fn();
|
|
39
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
40
|
+
throttle.schedule("a", 1); // leading fire
|
|
41
|
+
jest.advanceTimersByTime(100);
|
|
42
|
+
// No trailing fire — only the leading call
|
|
43
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
44
|
+
});
|
|
45
|
+
it("fires periodically during continuous rapid calls", () => {
|
|
46
|
+
const fn = jest.fn();
|
|
47
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
48
|
+
// Simulate rapid streaming chunks every 30ms for 350ms
|
|
49
|
+
throttle.schedule("a", 1); // t=0, leading fire
|
|
50
|
+
jest.advanceTimersByTime(30);
|
|
51
|
+
throttle.schedule("a", 2); // t=30
|
|
52
|
+
jest.advanceTimersByTime(30);
|
|
53
|
+
throttle.schedule("a", 3); // t=60
|
|
54
|
+
jest.advanceTimersByTime(30);
|
|
55
|
+
throttle.schedule("a", 4); // t=90
|
|
56
|
+
jest.advanceTimersByTime(10);
|
|
57
|
+
// t=100: cooldown expires, trailing fires with value 4
|
|
58
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
59
|
+
expect(fn).toHaveBeenLastCalledWith("a", 4);
|
|
60
|
+
jest.advanceTimersByTime(20);
|
|
61
|
+
throttle.schedule("a", 5); // t=120
|
|
62
|
+
jest.advanceTimersByTime(30);
|
|
63
|
+
throttle.schedule("a", 6); // t=150
|
|
64
|
+
jest.advanceTimersByTime(30);
|
|
65
|
+
throttle.schedule("a", 7); // t=180
|
|
66
|
+
jest.advanceTimersByTime(20);
|
|
67
|
+
// t=200: second cooldown expires, trailing fires with value 7
|
|
68
|
+
expect(fn).toHaveBeenCalledTimes(3);
|
|
69
|
+
expect(fn).toHaveBeenLastCalledWith("a", 7);
|
|
70
|
+
});
|
|
71
|
+
it("tracks keys independently", () => {
|
|
72
|
+
const fn = jest.fn();
|
|
73
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
74
|
+
throttle.schedule("a", 1); // leading fire for "a"
|
|
75
|
+
jest.advanceTimersByTime(50);
|
|
76
|
+
throttle.schedule("b", 2); // leading fire for "b"
|
|
77
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
78
|
+
expect(fn).toHaveBeenCalledWith("a", 1);
|
|
79
|
+
expect(fn).toHaveBeenCalledWith("b", 2);
|
|
80
|
+
});
|
|
81
|
+
it("tracks keys independently with trailing calls", () => {
|
|
82
|
+
const fn = jest.fn();
|
|
83
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
84
|
+
throttle.schedule("a", 1); // leading fire for "a"
|
|
85
|
+
throttle.schedule("a", 2); // queued trailing for "a"
|
|
86
|
+
jest.advanceTimersByTime(50);
|
|
87
|
+
throttle.schedule("b", 3); // leading fire for "b"
|
|
88
|
+
throttle.schedule("b", 4); // queued trailing for "b"
|
|
89
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
90
|
+
jest.advanceTimersByTime(50);
|
|
91
|
+
// t=100: "a" trailing fires
|
|
92
|
+
expect(fn).toHaveBeenCalledTimes(3);
|
|
93
|
+
expect(fn).toHaveBeenCalledWith("a", 2);
|
|
94
|
+
jest.advanceTimersByTime(50);
|
|
95
|
+
// t=150: "b" trailing fires
|
|
96
|
+
expect(fn).toHaveBeenCalledTimes(4);
|
|
97
|
+
expect(fn).toHaveBeenCalledWith("b", 4);
|
|
98
|
+
});
|
|
99
|
+
it("flush() fires all pending trailing calls immediately", () => {
|
|
100
|
+
const fn = jest.fn();
|
|
101
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
102
|
+
throttle.schedule("a", 1); // leading fire
|
|
103
|
+
throttle.schedule("a", 2); // queued trailing
|
|
104
|
+
throttle.schedule("b", 3); // leading fire
|
|
105
|
+
throttle.schedule("b", 4); // queued trailing
|
|
106
|
+
expect(fn).toHaveBeenCalledTimes(2); // two leading fires
|
|
107
|
+
throttle.flush();
|
|
108
|
+
expect(fn).toHaveBeenCalledTimes(4); // two trailing fires
|
|
109
|
+
expect(fn).toHaveBeenCalledWith("a", 2);
|
|
110
|
+
expect(fn).toHaveBeenCalledWith("b", 4);
|
|
111
|
+
// Timers should be cancelled — no double-fire
|
|
112
|
+
jest.advanceTimersByTime(200);
|
|
113
|
+
expect(fn).toHaveBeenCalledTimes(4);
|
|
114
|
+
});
|
|
115
|
+
it("flush() is a no-op when nothing is pending", () => {
|
|
116
|
+
const fn = jest.fn();
|
|
117
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
118
|
+
throttle.flush();
|
|
119
|
+
expect(fn).not.toHaveBeenCalled();
|
|
120
|
+
});
|
|
121
|
+
it("flush() skips keys with no trailing value", () => {
|
|
122
|
+
const fn = jest.fn();
|
|
123
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
124
|
+
throttle.schedule("a", 1); // leading fire, no trailing queued
|
|
125
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
126
|
+
throttle.flush();
|
|
127
|
+
// No trailing to fire — still just the one leading call
|
|
128
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
129
|
+
});
|
|
130
|
+
it("becomes idle after trailing fire with no new calls", () => {
|
|
131
|
+
const fn = jest.fn();
|
|
132
|
+
const throttle = createKeyedThrottle(fn, 100);
|
|
133
|
+
throttle.schedule("a", 1); // leading
|
|
134
|
+
throttle.schedule("a", 2); // trailing queued
|
|
135
|
+
jest.advanceTimersByTime(100); // trailing fires
|
|
136
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
137
|
+
jest.advanceTimersByTime(100); // cooldown after trailing — no new calls
|
|
138
|
+
expect(fn).toHaveBeenCalledTimes(2); // no extra fires
|
|
139
|
+
// New call should fire immediately (leading again)
|
|
140
|
+
throttle.schedule("a", 3);
|
|
141
|
+
expect(fn).toHaveBeenCalledTimes(3);
|
|
142
|
+
expect(fn).toHaveBeenLastCalledWith("a", 3);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
//# sourceMappingURL=keyed-throttle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyed-throttle.test.js","sourceRoot":"","sources":["../../../src/v1/utils/keyed-throttle.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { createKeyedThrottle } from \"./keyed-throttle\";\n\ndescribe(\"createKeyedThrottle\", () => {\n beforeEach(() => {\n jest.useFakeTimers();\n });\n\n afterEach(() => {\n jest.useRealTimers();\n });\n\n it(\"fires immediately on first call (leading edge)\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1);\n expect(fn).toHaveBeenCalledTimes(1);\n expect(fn).toHaveBeenCalledWith(\"a\", 1);\n });\n\n it(\"does not fire again during cooldown window\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1);\n throttle.schedule(\"a\", 2);\n throttle.schedule(\"a\", 3);\n\n // Only the leading call should have fired\n expect(fn).toHaveBeenCalledTimes(1);\n expect(fn).toHaveBeenCalledWith(\"a\", 1);\n });\n\n it(\"fires trailing call with latest value after cooldown\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1); // leading fire\n throttle.schedule(\"a\", 2);\n throttle.schedule(\"a\", 3);\n\n jest.advanceTimersByTime(100);\n\n // Trailing fire with latest value\n expect(fn).toHaveBeenCalledTimes(2);\n expect(fn).toHaveBeenLastCalledWith(\"a\", 3);\n });\n\n it(\"does not fire trailing call if no new values arrived\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1); // leading fire\n\n jest.advanceTimersByTime(100);\n\n // No trailing fire — only the leading call\n expect(fn).toHaveBeenCalledTimes(1);\n });\n\n it(\"fires periodically during continuous rapid calls\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n // Simulate rapid streaming chunks every 30ms for 350ms\n throttle.schedule(\"a\", 1); // t=0, leading fire\n jest.advanceTimersByTime(30);\n throttle.schedule(\"a\", 2); // t=30\n jest.advanceTimersByTime(30);\n throttle.schedule(\"a\", 3); // t=60\n jest.advanceTimersByTime(30);\n throttle.schedule(\"a\", 4); // t=90\n jest.advanceTimersByTime(10);\n // t=100: cooldown expires, trailing fires with value 4\n expect(fn).toHaveBeenCalledTimes(2);\n expect(fn).toHaveBeenLastCalledWith(\"a\", 4);\n\n jest.advanceTimersByTime(20);\n throttle.schedule(\"a\", 5); // t=120\n jest.advanceTimersByTime(30);\n throttle.schedule(\"a\", 6); // t=150\n jest.advanceTimersByTime(30);\n throttle.schedule(\"a\", 7); // t=180\n jest.advanceTimersByTime(20);\n // t=200: second cooldown expires, trailing fires with value 7\n expect(fn).toHaveBeenCalledTimes(3);\n expect(fn).toHaveBeenLastCalledWith(\"a\", 7);\n });\n\n it(\"tracks keys independently\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1); // leading fire for \"a\"\n jest.advanceTimersByTime(50);\n throttle.schedule(\"b\", 2); // leading fire for \"b\"\n\n expect(fn).toHaveBeenCalledTimes(2);\n expect(fn).toHaveBeenCalledWith(\"a\", 1);\n expect(fn).toHaveBeenCalledWith(\"b\", 2);\n });\n\n it(\"tracks keys independently with trailing calls\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1); // leading fire for \"a\"\n throttle.schedule(\"a\", 2); // queued trailing for \"a\"\n jest.advanceTimersByTime(50);\n throttle.schedule(\"b\", 3); // leading fire for \"b\"\n throttle.schedule(\"b\", 4); // queued trailing for \"b\"\n\n expect(fn).toHaveBeenCalledTimes(2);\n\n jest.advanceTimersByTime(50);\n // t=100: \"a\" trailing fires\n expect(fn).toHaveBeenCalledTimes(3);\n expect(fn).toHaveBeenCalledWith(\"a\", 2);\n\n jest.advanceTimersByTime(50);\n // t=150: \"b\" trailing fires\n expect(fn).toHaveBeenCalledTimes(4);\n expect(fn).toHaveBeenCalledWith(\"b\", 4);\n });\n\n it(\"flush() fires all pending trailing calls immediately\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1); // leading fire\n throttle.schedule(\"a\", 2); // queued trailing\n throttle.schedule(\"b\", 3); // leading fire\n throttle.schedule(\"b\", 4); // queued trailing\n\n expect(fn).toHaveBeenCalledTimes(2); // two leading fires\n\n throttle.flush();\n\n expect(fn).toHaveBeenCalledTimes(4); // two trailing fires\n expect(fn).toHaveBeenCalledWith(\"a\", 2);\n expect(fn).toHaveBeenCalledWith(\"b\", 4);\n\n // Timers should be cancelled — no double-fire\n jest.advanceTimersByTime(200);\n expect(fn).toHaveBeenCalledTimes(4);\n });\n\n it(\"flush() is a no-op when nothing is pending\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.flush();\n expect(fn).not.toHaveBeenCalled();\n });\n\n it(\"flush() skips keys with no trailing value\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1); // leading fire, no trailing queued\n\n expect(fn).toHaveBeenCalledTimes(1);\n\n throttle.flush();\n\n // No trailing to fire — still just the one leading call\n expect(fn).toHaveBeenCalledTimes(1);\n });\n\n it(\"becomes idle after trailing fire with no new calls\", () => {\n const fn = jest.fn();\n const throttle = createKeyedThrottle(fn, 100);\n\n throttle.schedule(\"a\", 1); // leading\n throttle.schedule(\"a\", 2); // trailing queued\n\n jest.advanceTimersByTime(100); // trailing fires\n expect(fn).toHaveBeenCalledTimes(2);\n\n jest.advanceTimersByTime(100); // cooldown after trailing — no new calls\n expect(fn).toHaveBeenCalledTimes(2); // no extra fires\n\n // New call should fire immediately (leading again)\n throttle.schedule(\"a\", 3);\n expect(fn).toHaveBeenCalledTimes(3);\n expect(fn).toHaveBeenLastCalledWith(\"a\", 3);\n });\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-conversion.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/registry-conversion.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,SAAS,EACT,0BAA0B,EAC3B,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AAGvF,KAAK,kBAAkB,GAAG,eAAe,CAAC,kBAAkB,CAAC;AAC7D,KAAK,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC;AAEjC;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,mBAAmB,GAC7B,kBAAkB,CAepB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EACN,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,kBAAkB,EAAE,CAmBtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,GAAG,0BAA0B,GAC3C,IAAI,
|
|
1
|
+
{"version":3,"file":"registry-conversion.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/registry-conversion.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,SAAS,EACT,0BAA0B,EAC3B,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iDAAiD,CAAC;AAGvF,KAAK,kBAAkB,GAAG,eAAe,CAAC,kBAAkB,CAAC;AAC7D,KAAK,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC;AAEjC;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,mBAAmB,GAC7B,kBAAkB,CAepB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EACN,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,GACnC,kBAAkB,EAAE,CAmBtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,GAAG,0BAA0B,GAC3C,IAAI,CA0BN;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EACD,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,0BAA0B,CAAC,GACtD,GAAG,CAAC,MAAM,EAAE,SAAS,GAAG,0BAA0B,CAAC,GACtD,IAAI,EAAE,CAiBR"}
|
|
@@ -69,6 +69,7 @@ export function toAvailableTool(tool) {
|
|
|
69
69
|
name: tool.name,
|
|
70
70
|
description: tool.description,
|
|
71
71
|
inputSchema: inputSchema,
|
|
72
|
+
...(tool.maxCalls !== undefined ? { maxCalls: tool.maxCalls } : {}),
|
|
72
73
|
};
|
|
73
74
|
}
|
|
74
75
|
// Check for deprecated toolSchema format (UnsupportedSchemaTamboTool)
|
|
@@ -78,6 +79,7 @@ export function toAvailableTool(tool) {
|
|
|
78
79
|
name: tool.name,
|
|
79
80
|
description: tool.description,
|
|
80
81
|
inputSchema: inputSchema,
|
|
82
|
+
...(tool.maxCalls !== undefined ? { maxCalls: tool.maxCalls } : {}),
|
|
81
83
|
};
|
|
82
84
|
}
|
|
83
85
|
throw new Error(`Tool "${tool.name}" missing inputSchema or toolSchema - required for v1 API`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-conversion.js","sourceRoot":"","sources":["../../../src/v1/utils/registry-conversion.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAOzD;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA8B;IAE9B,mFAAmF;IACnF,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,cAAc,SAAS,CAAC,IAAI,uCAAuC,CACpE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,WAAW,EAAE,SAAS,CAAC,KAAgC;QACvD,sEAAsE;QACtE,yEAAyE;KAC1E,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAEoC;IAEpC,MAAM,OAAO,GAAyB,EAAE,CAAC;IAEzC,MAAM,OAAO,GACX,UAAU,YAAY,GAAG;QACvB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAClC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEjC,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,OAAO,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,uBAAuB,IAAI,uBAAuB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC3G,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,IAA4C;IAE5C,gEAAgE;IAChE,IAAI,aAAa,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,WAAW,GAAgB,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtE,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,WAAsC;
|
|
1
|
+
{"version":3,"file":"registry-conversion.js","sourceRoot":"","sources":["../../../src/v1/utils/registry-conversion.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Registry Conversion Utilities\n *\n * Converts beta SDK component/tool types to v1 API format.\n * Reuses the beta SDK's TamboRegistryProvider but provides conversion\n * utilities for sending component/tool metadata to the v1 API.\n */\n\nimport type { JSONSchema7 } from \"json-schema\";\nimport type {\n RegisteredComponent,\n TamboTool,\n UnsupportedSchemaTamboTool,\n} from \"../../model/component-metadata\";\nimport { schemaToJsonSchema } from \"../../schema/schema\";\nimport type { RunCreateParams } from \"@tambo-ai/typescript-sdk/resources/threads/runs\";\n\n// Use the SDK's types for API requests\ntype AvailableComponent = RunCreateParams.AvailableComponent;\ntype Tool = RunCreateParams.Tool;\n\n/**\n * Convert a registered component to v1 API format.\n *\n * Transforms RegisteredComponent (from the registry, with props already converted\n * to JSON Schema) to AvailableComponent (v1 API format).\n * @param component - Component from beta SDK registry (already has props as JSON Schema)\n * @returns Component metadata in v1 API format\n * @throws {Error} if props is missing\n */\nexport function toAvailableComponent(\n component: RegisteredComponent,\n): AvailableComponent {\n // props is the JSON Schema that was converted from propsSchema during registration\n if (!component.props) {\n throw new Error(\n `Component \"${component.name}\" missing props - required for v1 API`,\n );\n }\n\n return {\n name: component.name,\n description: component.description,\n propsSchema: component.props as Record<string, unknown>,\n // stateSchema is v1-specific and not available in beta SDK components\n // Components can still have state, but schema must be defined separately\n };\n}\n\n/**\n * Convert multiple registered components to v1 API format.\n *\n * Transforms a Record/Map of RegisteredComponents to an array of AvailableComponents.\n * Components without props will be logged as warnings and skipped.\n * @param components - Record or Map of components from beta SDK registry\n * @returns Array of component metadata in v1 API format\n */\nexport function toAvailableComponents(\n components:\n | Record<string, RegisteredComponent>\n | Map<string, RegisteredComponent>,\n): AvailableComponent[] {\n const results: AvailableComponent[] = [];\n\n const entries =\n components instanceof Map\n ? Array.from(components.entries())\n : Object.entries(components);\n\n for (const [name, component] of entries) {\n try {\n results.push(toAvailableComponent(component));\n } catch (error) {\n console.warn(\n `Skipping component \"${name}\" in v1 conversion: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return results;\n}\n\n/**\n * Convert a registered tool to v1 API format.\n *\n * Transforms TamboTool or UnsupportedSchemaTamboTool (beta SDK format with\n * Standard Schema support) to Tool (v1 API format requiring JSON Schema).\n * Handles both new inputSchema and deprecated toolSchema formats.\n * @param tool - Tool from beta SDK registry\n * @returns Tool metadata in v1 API format\n * @throws {Error} if schema conversion fails or schema is missing\n */\nexport function toAvailableTool(\n tool: TamboTool | UnsupportedSchemaTamboTool,\n): Tool {\n // Check for inputSchema (modern format - required in TamboTool)\n if (\"inputSchema\" in tool && tool.inputSchema) {\n const inputSchema: JSONSchema7 = schemaToJsonSchema(tool.inputSchema);\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: inputSchema as Record<string, unknown>,\n ...(tool.maxCalls !== undefined ? { maxCalls: tool.maxCalls } : {}),\n };\n }\n\n // Check for deprecated toolSchema format (UnsupportedSchemaTamboTool)\n if (\"toolSchema\" in tool && tool.toolSchema) {\n const inputSchema: JSONSchema7 = schemaToJsonSchema(tool.toolSchema);\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: inputSchema as Record<string, unknown>,\n ...(tool.maxCalls !== undefined ? { maxCalls: tool.maxCalls } : {}),\n };\n }\n\n throw new Error(\n `Tool \"${tool.name}\" missing inputSchema or toolSchema - required for v1 API`,\n );\n}\n\n/**\n * Convert multiple registered tools to v1 API format.\n *\n * Transforms a Record/Map of TamboTools or UnsupportedSchemaTamboTool to an array\n * of Tools. Tools without inputSchema/toolSchema will be logged as warnings\n * and skipped.\n * @param tools - Record or Map of tools from beta SDK registry\n * @returns Array of tool metadata in v1 API format\n */\nexport function toAvailableTools(\n tools:\n | Record<string, TamboTool | UnsupportedSchemaTamboTool>\n | Map<string, TamboTool | UnsupportedSchemaTamboTool>,\n): Tool[] {\n const results: Tool[] = [];\n\n const entries =\n tools instanceof Map ? Array.from(tools.entries()) : Object.entries(tools);\n\n for (const [name, tool] of entries) {\n try {\n results.push(toAvailableTool(tool));\n } catch (error) {\n console.warn(\n `Skipping tool \"${name}\" in v1 conversion: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n return results;\n}\n"]}
|
|
@@ -129,6 +129,29 @@ describe("registry-conversion", () => {
|
|
|
129
129
|
expect(result.inputSchema).toBeDefined();
|
|
130
130
|
expect(result.inputSchema.type).toBe("object");
|
|
131
131
|
});
|
|
132
|
+
it("includes maxCalls when set", () => {
|
|
133
|
+
const tool = {
|
|
134
|
+
name: "limited_tool",
|
|
135
|
+
description: "Tool with call limit",
|
|
136
|
+
tool: async () => ({}),
|
|
137
|
+
inputSchema: z.object({ x: z.string() }),
|
|
138
|
+
outputSchema: z.any(),
|
|
139
|
+
maxCalls: 3,
|
|
140
|
+
};
|
|
141
|
+
const result = toAvailableTool(tool);
|
|
142
|
+
expect(result.maxCalls).toBe(3);
|
|
143
|
+
});
|
|
144
|
+
it("omits maxCalls when not set", () => {
|
|
145
|
+
const tool = {
|
|
146
|
+
name: "unlimited_tool",
|
|
147
|
+
description: "Tool without call limit",
|
|
148
|
+
tool: async () => ({}),
|
|
149
|
+
inputSchema: z.object({ x: z.string() }),
|
|
150
|
+
outputSchema: z.any(),
|
|
151
|
+
};
|
|
152
|
+
const result = toAvailableTool(tool);
|
|
153
|
+
expect(result).not.toHaveProperty("maxCalls");
|
|
154
|
+
});
|
|
132
155
|
it("throws when schema is missing", () => {
|
|
133
156
|
const tool = {
|
|
134
157
|
name: "bad_tool",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-conversion.test.js","sourceRoot":"","sources":["../../../src/v1/utils/registry-conversion.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type {\n RegisteredComponent,\n TamboTool,\n} from \"../../model/component-metadata\";\nimport {\n toAvailableComponent,\n toAvailableComponents,\n toAvailableTool,\n toAvailableTools,\n} from \"./registry-conversion\";\n\ndescribe(\"registry-conversion\", () => {\n describe(\"toAvailableComponent\", () => {\n it(\"converts a component with props (JSON Schema)\", () => {\n // RegisteredComponent has props already converted to JSON Schema\n const component: RegisteredComponent = {\n name: \"WeatherCard\",\n description: \"Displays weather information\",\n component: () => null,\n props: {\n type: \"object\",\n properties: {\n city: { type: \"string\" },\n temperature: { type: \"number\" },\n },\n required: [\"city\", \"temperature\"],\n },\n contextTools: [],\n };\n\n const result = toAvailableComponent(component);\n\n expect(result.name).toBe(\"WeatherCard\");\n expect(result.description).toBe(\"Displays weather information\");\n expect(result.propsSchema).toBeDefined();\n expect((result.propsSchema as Record<string, unknown>).type).toBe(\n \"object\",\n );\n });\n\n it(\"throws when props is missing\", () => {\n const component = {\n name: \"BadComponent\",\n description: \"Missing schema\",\n component: () => null,\n contextTools: [],\n } as unknown as RegisteredComponent;\n\n expect(() => toAvailableComponent(component)).toThrow(\n 'Component \"BadComponent\" missing props',\n );\n });\n });\n\n describe(\"toAvailableComponents\", () => {\n it(\"converts a Record of components\", () => {\n const components: Record<string, RegisteredComponent> = {\n Card: {\n name: \"Card\",\n description: \"A card component\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { title: { type: \"string\" } },\n required: [\"title\"],\n },\n contextTools: [],\n },\n Button: {\n name: \"Button\",\n description: \"A button component\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { label: { type: \"string\" } },\n required: [\"label\"],\n },\n contextTools: [],\n },\n };\n\n const result = toAvailableComponents(components);\n\n expect(result).toHaveLength(2);\n expect(result.map((c) => c.name)).toContain(\"Card\");\n expect(result.map((c) => c.name)).toContain(\"Button\");\n });\n\n it(\"converts a Map of components\", () => {\n const components = new Map<string, RegisteredComponent>([\n [\n \"Card\",\n {\n name: \"Card\",\n description: \"A card\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { title: { type: \"string\" } },\n required: [\"title\"],\n },\n contextTools: [],\n },\n ],\n ]);\n\n const result = toAvailableComponents(components);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"Card\");\n });\n\n it(\"skips invalid components and logs warning\", () => {\n const warnSpy = jest.spyOn(console, \"warn\").mockImplementation(() => {});\n\n const components: Record<string, RegisteredComponent> = {\n Valid: {\n name: \"Valid\",\n description: \"Valid component\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { x: { type: \"string\" } },\n required: [\"x\"],\n },\n contextTools: [],\n },\n Invalid: {\n name: \"Invalid\",\n description: \"Missing schema\",\n component: () => null,\n contextTools: [],\n } as unknown as RegisteredComponent,\n };\n\n const result = toAvailableComponents(components);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"Valid\");\n expect(warnSpy).toHaveBeenCalledWith(\n expect.stringContaining('Skipping component \"Invalid\"'),\n );\n\n warnSpy.mockRestore();\n });\n });\n\n describe(\"toAvailableTool\", () => {\n it(\"converts a tool with inputSchema\", () => {\n const tool: TamboTool = {\n name: \"get_weather\",\n description: \"Gets weather for a city\",\n tool: async () => ({ temp: 72 }),\n inputSchema: z.object({ city: z.string() }),\n outputSchema: z.any(),\n };\n\n const result = toAvailableTool(tool);\n\n expect(result.name).toBe(\"get_weather\");\n expect(result.description).toBe(\"Gets weather for a city\");\n expect(result.inputSchema).toBeDefined();\n expect((result.inputSchema as Record<string, unknown>).type).toBe(\n \"object\",\n );\n });\n\n it(\"throws when schema is missing\", () => {\n const tool = {\n name: \"bad_tool\",\n description: \"Missing schema\",\n tool: async () => ({}),\n } as unknown as TamboTool;\n\n expect(() => toAvailableTool(tool)).toThrow(\n 'Tool \"bad_tool\" missing inputSchema or toolSchema',\n );\n });\n });\n\n describe(\"toAvailableTools\", () => {\n it(\"converts a Record of tools\", () => {\n const tools: Record<string, TamboTool> = {\n search: {\n name: \"search\",\n description: \"Search the web\",\n tool: async () => [],\n inputSchema: z.object({ query: z.string() }),\n outputSchema: z.any(),\n },\n calculate: {\n name: \"calculate\",\n description: \"Calculate expression\",\n tool: async () => 0,\n inputSchema: z.object({ expr: z.string() }),\n outputSchema: z.any(),\n },\n };\n\n const result = toAvailableTools(tools);\n\n expect(result).toHaveLength(2);\n expect(result.map((t) => t.name)).toContain(\"search\");\n expect(result.map((t) => t.name)).toContain(\"calculate\");\n });\n\n it(\"converts a Map of tools\", () => {\n const tools = new Map<string, TamboTool>([\n [\n \"fetch\",\n {\n name: \"fetch\",\n description: \"Fetch data\",\n tool: async () => null,\n inputSchema: z.object({ url: z.string() }),\n outputSchema: z.any(),\n },\n ],\n ]);\n\n const result = toAvailableTools(tools);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"fetch\");\n });\n\n it(\"skips invalid tools and logs warning\", () => {\n const warnSpy = jest.spyOn(console, \"warn\").mockImplementation(() => {});\n\n const tools: Record<string, TamboTool> = {\n valid: {\n name: \"valid\",\n description: \"Valid tool\",\n tool: async () => null,\n inputSchema: z.object({ x: z.number() }),\n outputSchema: z.any(),\n },\n invalid: {\n name: \"invalid\",\n description: \"Missing schema\",\n tool: async () => null,\n } as unknown as TamboTool,\n };\n\n const result = toAvailableTools(tools);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"valid\");\n expect(warnSpy).toHaveBeenCalledWith(\n expect.stringContaining('Skipping tool \"invalid\"'),\n );\n\n warnSpy.mockRestore();\n });\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"registry-conversion.test.js","sourceRoot":"","sources":["../../../src/v1/utils/registry-conversion.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport type {\n RegisteredComponent,\n TamboTool,\n} from \"../../model/component-metadata\";\nimport {\n toAvailableComponent,\n toAvailableComponents,\n toAvailableTool,\n toAvailableTools,\n} from \"./registry-conversion\";\n\ndescribe(\"registry-conversion\", () => {\n describe(\"toAvailableComponent\", () => {\n it(\"converts a component with props (JSON Schema)\", () => {\n // RegisteredComponent has props already converted to JSON Schema\n const component: RegisteredComponent = {\n name: \"WeatherCard\",\n description: \"Displays weather information\",\n component: () => null,\n props: {\n type: \"object\",\n properties: {\n city: { type: \"string\" },\n temperature: { type: \"number\" },\n },\n required: [\"city\", \"temperature\"],\n },\n contextTools: [],\n };\n\n const result = toAvailableComponent(component);\n\n expect(result.name).toBe(\"WeatherCard\");\n expect(result.description).toBe(\"Displays weather information\");\n expect(result.propsSchema).toBeDefined();\n expect((result.propsSchema as Record<string, unknown>).type).toBe(\n \"object\",\n );\n });\n\n it(\"throws when props is missing\", () => {\n const component = {\n name: \"BadComponent\",\n description: \"Missing schema\",\n component: () => null,\n contextTools: [],\n } as unknown as RegisteredComponent;\n\n expect(() => toAvailableComponent(component)).toThrow(\n 'Component \"BadComponent\" missing props',\n );\n });\n });\n\n describe(\"toAvailableComponents\", () => {\n it(\"converts a Record of components\", () => {\n const components: Record<string, RegisteredComponent> = {\n Card: {\n name: \"Card\",\n description: \"A card component\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { title: { type: \"string\" } },\n required: [\"title\"],\n },\n contextTools: [],\n },\n Button: {\n name: \"Button\",\n description: \"A button component\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { label: { type: \"string\" } },\n required: [\"label\"],\n },\n contextTools: [],\n },\n };\n\n const result = toAvailableComponents(components);\n\n expect(result).toHaveLength(2);\n expect(result.map((c) => c.name)).toContain(\"Card\");\n expect(result.map((c) => c.name)).toContain(\"Button\");\n });\n\n it(\"converts a Map of components\", () => {\n const components = new Map<string, RegisteredComponent>([\n [\n \"Card\",\n {\n name: \"Card\",\n description: \"A card\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { title: { type: \"string\" } },\n required: [\"title\"],\n },\n contextTools: [],\n },\n ],\n ]);\n\n const result = toAvailableComponents(components);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"Card\");\n });\n\n it(\"skips invalid components and logs warning\", () => {\n const warnSpy = jest.spyOn(console, \"warn\").mockImplementation(() => {});\n\n const components: Record<string, RegisteredComponent> = {\n Valid: {\n name: \"Valid\",\n description: \"Valid component\",\n component: () => null,\n props: {\n type: \"object\",\n properties: { x: { type: \"string\" } },\n required: [\"x\"],\n },\n contextTools: [],\n },\n Invalid: {\n name: \"Invalid\",\n description: \"Missing schema\",\n component: () => null,\n contextTools: [],\n } as unknown as RegisteredComponent,\n };\n\n const result = toAvailableComponents(components);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"Valid\");\n expect(warnSpy).toHaveBeenCalledWith(\n expect.stringContaining('Skipping component \"Invalid\"'),\n );\n\n warnSpy.mockRestore();\n });\n });\n\n describe(\"toAvailableTool\", () => {\n it(\"converts a tool with inputSchema\", () => {\n const tool: TamboTool = {\n name: \"get_weather\",\n description: \"Gets weather for a city\",\n tool: async () => ({ temp: 72 }),\n inputSchema: z.object({ city: z.string() }),\n outputSchema: z.any(),\n };\n\n const result = toAvailableTool(tool);\n\n expect(result.name).toBe(\"get_weather\");\n expect(result.description).toBe(\"Gets weather for a city\");\n expect(result.inputSchema).toBeDefined();\n expect((result.inputSchema as Record<string, unknown>).type).toBe(\n \"object\",\n );\n });\n\n it(\"includes maxCalls when set\", () => {\n const tool: TamboTool = {\n name: \"limited_tool\",\n description: \"Tool with call limit\",\n tool: async () => ({}),\n inputSchema: z.object({ x: z.string() }),\n outputSchema: z.any(),\n maxCalls: 3,\n };\n\n const result = toAvailableTool(tool);\n\n expect(result.maxCalls).toBe(3);\n });\n\n it(\"omits maxCalls when not set\", () => {\n const tool: TamboTool = {\n name: \"unlimited_tool\",\n description: \"Tool without call limit\",\n tool: async () => ({}),\n inputSchema: z.object({ x: z.string() }),\n outputSchema: z.any(),\n };\n\n const result = toAvailableTool(tool);\n\n expect(result).not.toHaveProperty(\"maxCalls\");\n });\n\n it(\"throws when schema is missing\", () => {\n const tool = {\n name: \"bad_tool\",\n description: \"Missing schema\",\n tool: async () => ({}),\n } as unknown as TamboTool;\n\n expect(() => toAvailableTool(tool)).toThrow(\n 'Tool \"bad_tool\" missing inputSchema or toolSchema',\n );\n });\n });\n\n describe(\"toAvailableTools\", () => {\n it(\"converts a Record of tools\", () => {\n const tools: Record<string, TamboTool> = {\n search: {\n name: \"search\",\n description: \"Search the web\",\n tool: async () => [],\n inputSchema: z.object({ query: z.string() }),\n outputSchema: z.any(),\n },\n calculate: {\n name: \"calculate\",\n description: \"Calculate expression\",\n tool: async () => 0,\n inputSchema: z.object({ expr: z.string() }),\n outputSchema: z.any(),\n },\n };\n\n const result = toAvailableTools(tools);\n\n expect(result).toHaveLength(2);\n expect(result.map((t) => t.name)).toContain(\"search\");\n expect(result.map((t) => t.name)).toContain(\"calculate\");\n });\n\n it(\"converts a Map of tools\", () => {\n const tools = new Map<string, TamboTool>([\n [\n \"fetch\",\n {\n name: \"fetch\",\n description: \"Fetch data\",\n tool: async () => null,\n inputSchema: z.object({ url: z.string() }),\n outputSchema: z.any(),\n },\n ],\n ]);\n\n const result = toAvailableTools(tools);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"fetch\");\n });\n\n it(\"skips invalid tools and logs warning\", () => {\n const warnSpy = jest.spyOn(console, \"warn\").mockImplementation(() => {});\n\n const tools: Record<string, TamboTool> = {\n valid: {\n name: \"valid\",\n description: \"Valid tool\",\n tool: async () => null,\n inputSchema: z.object({ x: z.number() }),\n outputSchema: z.any(),\n },\n invalid: {\n name: \"invalid\",\n description: \"Missing schema\",\n tool: async () => null,\n } as unknown as TamboTool,\n };\n\n const result = toAvailableTools(tools);\n\n expect(result).toHaveLength(1);\n expect(result[0].name).toBe(\"valid\");\n expect(warnSpy).toHaveBeenCalledWith(\n expect.stringContaining('Skipping tool \"invalid\"'),\n );\n\n warnSpy.mockRestore();\n });\n });\n});\n"]}
|
|
@@ -26,6 +26,16 @@ export declare class ToolCallTracker {
|
|
|
26
26
|
* @throws {Error} If JSON parsing fails on TOOL_CALL_END (fail-fast, no silent fallback)
|
|
27
27
|
*/
|
|
28
28
|
handleEvent(event: AGUIEvent): void;
|
|
29
|
+
/**
|
|
30
|
+
* Gets the name and accumulated args for a tool call that is still accumulating.
|
|
31
|
+
* Used by the event loop to get tool state for partial JSON parsing.
|
|
32
|
+
* @param toolCallId - ID of the tool call to look up
|
|
33
|
+
* @returns The tool name and raw accumulated args string, or undefined if not found
|
|
34
|
+
*/
|
|
35
|
+
getAccumulatingToolCall(toolCallId: string): {
|
|
36
|
+
name: string;
|
|
37
|
+
accumulatedArgs: string;
|
|
38
|
+
} | undefined;
|
|
29
39
|
/**
|
|
30
40
|
* Gets tool calls for the given IDs, filtered to only those that exist.
|
|
31
41
|
* @param toolCallIds - IDs of tool calls to retrieve
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-call-tracker.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/tool-call-tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,gBAAgB,CAAsC;IAC9D,OAAO,CAAC,gBAAgB,CAA6B;IAErD;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAyCnC;;;;OAIG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;IAWrE;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI;CAM5C"}
|
|
1
|
+
{"version":3,"file":"tool-call-tracker.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/tool-call-tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,gBAAgB,CAAsC;IAC9D,OAAO,CAAC,gBAAgB,CAA6B;IAErD;;;;OAIG;IACH,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAyCnC;;;;;OAKG;IACH,uBAAuB,CACrB,UAAU,EAAE,MAAM,GACjB;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS;IAOxD;;;;OAIG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;IAWrE;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,IAAI;CAM5C"}
|
|
@@ -57,6 +57,19 @@ export class ToolCallTracker {
|
|
|
57
57
|
break;
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Gets the name and accumulated args for a tool call that is still accumulating.
|
|
62
|
+
* Used by the event loop to get tool state for partial JSON parsing.
|
|
63
|
+
* @param toolCallId - ID of the tool call to look up
|
|
64
|
+
* @returns The tool name and raw accumulated args string, or undefined if not found
|
|
65
|
+
*/
|
|
66
|
+
getAccumulatingToolCall(toolCallId) {
|
|
67
|
+
const toolCall = this.pendingToolCalls.get(toolCallId);
|
|
68
|
+
const args = this.accumulatingArgs.get(toolCallId);
|
|
69
|
+
if (!toolCall || args === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
return { name: toolCall.name, accumulatedArgs: args };
|
|
72
|
+
}
|
|
60
73
|
/**
|
|
61
74
|
* Gets tool calls for the given IDs, filtered to only those that exist.
|
|
62
75
|
* @param toolCallIds - IDs of tool calls to retrieve
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-call-tracker.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-call-tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAkB,MAAM,aAAa,CAAC;AAGxD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,eAAe;IAClB,gBAAgB,GAAG,IAAI,GAAG,EAA2B,CAAC;IACtD,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAErD;;;;OAIG;IACH,WAAW,CAAC,KAAgB;QAC1B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,SAAS,CAAC,eAAe;gBAC5B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE;oBAC1C,IAAI,EAAE,KAAK,CAAC,YAAY;oBACxB,KAAK,EAAE,EAAE;iBACV,CAAC,CAAC;gBACH,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBAChD,MAAM;YAER,KAAK,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;gBAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC5D,IAAI,CAAC,gBAAgB,CAAC,GAAG,CACvB,KAAK,CAAC,UAAU,EAChB,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAC9B,CAAC;gBACF,MAAM;YACR,CAAC;YAED,KAAK,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;gBAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC7D,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC;wBACH,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;oBAClE,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,sDAAsD;wBACtD,MAAM,IAAI,KAAK,CACb,2CAA2C,KAAK,CAAC,UAAU,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,WAAW,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/L,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,MAAM;YACR,CAAC;YAED;gBACE,oEAAoE;gBACpE,MAAM;QACV,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,gBAAgB,CAAC,WAAqB;QACpC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;QAClD,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/C,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,WAAqB;QAClC,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Tool Call Tracker for v1 API\n *\n * Tracks tool calls during streaming, accumulating arguments until complete.\n * Used by the send message hook to collect tool call state for execution.\n */\n\nimport { EventType, type AGUIEvent } from \"@ag-ui/core\";\nimport type { PendingToolCall } from \"./tool-executor\";\n\n/**\n * Tracks tool calls during streaming, accumulating arguments until complete.\n *\n * Tool calls arrive as a sequence of events:\n * 1. TOOL_CALL_START - initializes the tool call with name\n * 2. TOOL_CALL_ARGS (multiple) - streams JSON argument fragments\n * 3. TOOL_CALL_END - marks the tool call as complete, triggers JSON parsing\n *\n * This class accumulates these events and provides the complete tool call\n * data when requested for execution.\n */\nexport class ToolCallTracker {\n private pendingToolCalls = new Map<string, PendingToolCall>();\n private accumulatingArgs = new Map<string, string>();\n\n /**\n * Handles a streaming event, tracking tool call state as needed.\n * @param event - The streaming event to process\n * @throws {Error} If JSON parsing fails on TOOL_CALL_END (fail-fast, no silent fallback)\n */\n handleEvent(event: AGUIEvent): void {\n switch (event.type) {\n case EventType.TOOL_CALL_START:\n this.pendingToolCalls.set(event.toolCallId, {\n name: event.toolCallName,\n input: {},\n });\n this.accumulatingArgs.set(event.toolCallId, \"\");\n break;\n\n case EventType.TOOL_CALL_ARGS: {\n const current = this.accumulatingArgs.get(event.toolCallId);\n this.accumulatingArgs.set(\n event.toolCallId,\n (current ?? \"\") + event.delta,\n );\n break;\n }\n\n case EventType.TOOL_CALL_END: {\n const jsonStr = this.accumulatingArgs.get(event.toolCallId);\n const toolCall = this.pendingToolCalls.get(event.toolCallId);\n if (toolCall && jsonStr) {\n try {\n toolCall.input = JSON.parse(jsonStr) as Record<string, unknown>;\n } catch (error) {\n // Fail-fast: don't silently continue with empty input\n throw new Error(\n `Failed to parse tool call arguments for ${event.toolCallId}: ${error instanceof Error ? error.message : \"Unknown error\"}. JSON: ${jsonStr.slice(0, 100)}${jsonStr.length > 100 ? \"...\" : \"\"}`,\n );\n }\n }\n break;\n }\n\n default:\n // Other event types are ignored - only tool call events are tracked\n break;\n }\n }\n\n /**\n * Gets tool calls for the given IDs, filtered to only those that exist.\n * @param toolCallIds - IDs of tool calls to retrieve\n * @returns Map of tool call ID to pending tool call\n */\n getToolCallsById(toolCallIds: string[]): Map<string, PendingToolCall> {\n const result = new Map<string, PendingToolCall>();\n for (const id of toolCallIds) {\n const toolCall = this.pendingToolCalls.get(id);\n if (toolCall) {\n result.set(id, toolCall);\n }\n }\n return result;\n }\n\n /**\n * Clears tracked tool calls for the given IDs.\n * @param toolCallIds - IDs of tool calls to clear\n */\n clearToolCalls(toolCallIds: string[]): void {\n for (const id of toolCallIds) {\n this.pendingToolCalls.delete(id);\n this.accumulatingArgs.delete(id);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool-call-tracker.js","sourceRoot":"","sources":["../../../src/v1/utils/tool-call-tracker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAkB,MAAM,aAAa,CAAC;AAGxD;;;;;;;;;;GAUG;AACH,MAAM,OAAO,eAAe;IAClB,gBAAgB,GAAG,IAAI,GAAG,EAA2B,CAAC;IACtD,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAErD;;;;OAIG;IACH,WAAW,CAAC,KAAgB;QAC1B,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,SAAS,CAAC,eAAe;gBAC5B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE;oBAC1C,IAAI,EAAE,KAAK,CAAC,YAAY;oBACxB,KAAK,EAAE,EAAE;iBACV,CAAC,CAAC;gBACH,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;gBAChD,MAAM;YAER,KAAK,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;gBAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC5D,IAAI,CAAC,gBAAgB,CAAC,GAAG,CACvB,KAAK,CAAC,UAAU,EAChB,CAAC,OAAO,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAC9B,CAAC;gBACF,MAAM;YACR,CAAC;YAED,KAAK,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;gBAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBAC7D,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;oBACxB,IAAI,CAAC;wBACH,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;oBAClE,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,sDAAsD;wBACtD,MAAM,IAAI,KAAK,CACb,2CAA2C,KAAK,CAAC,UAAU,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,WAAW,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAC/L,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,MAAM;YACR,CAAC;YAED;gBACE,oEAAoE;gBACpE,MAAM;QACV,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,uBAAuB,CACrB,UAAkB;QAElB,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACtD,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,gBAAgB,CAAC,WAAqB;QACpC,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;QAClD,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/C,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,WAAqB;QAClC,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACjC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;CACF","sourcesContent":["/**\n * Tool Call Tracker for v1 API\n *\n * Tracks tool calls during streaming, accumulating arguments until complete.\n * Used by the send message hook to collect tool call state for execution.\n */\n\nimport { EventType, type AGUIEvent } from \"@ag-ui/core\";\nimport type { PendingToolCall } from \"./tool-executor\";\n\n/**\n * Tracks tool calls during streaming, accumulating arguments until complete.\n *\n * Tool calls arrive as a sequence of events:\n * 1. TOOL_CALL_START - initializes the tool call with name\n * 2. TOOL_CALL_ARGS (multiple) - streams JSON argument fragments\n * 3. TOOL_CALL_END - marks the tool call as complete, triggers JSON parsing\n *\n * This class accumulates these events and provides the complete tool call\n * data when requested for execution.\n */\nexport class ToolCallTracker {\n private pendingToolCalls = new Map<string, PendingToolCall>();\n private accumulatingArgs = new Map<string, string>();\n\n /**\n * Handles a streaming event, tracking tool call state as needed.\n * @param event - The streaming event to process\n * @throws {Error} If JSON parsing fails on TOOL_CALL_END (fail-fast, no silent fallback)\n */\n handleEvent(event: AGUIEvent): void {\n switch (event.type) {\n case EventType.TOOL_CALL_START:\n this.pendingToolCalls.set(event.toolCallId, {\n name: event.toolCallName,\n input: {},\n });\n this.accumulatingArgs.set(event.toolCallId, \"\");\n break;\n\n case EventType.TOOL_CALL_ARGS: {\n const current = this.accumulatingArgs.get(event.toolCallId);\n this.accumulatingArgs.set(\n event.toolCallId,\n (current ?? \"\") + event.delta,\n );\n break;\n }\n\n case EventType.TOOL_CALL_END: {\n const jsonStr = this.accumulatingArgs.get(event.toolCallId);\n const toolCall = this.pendingToolCalls.get(event.toolCallId);\n if (toolCall && jsonStr) {\n try {\n toolCall.input = JSON.parse(jsonStr) as Record<string, unknown>;\n } catch (error) {\n // Fail-fast: don't silently continue with empty input\n throw new Error(\n `Failed to parse tool call arguments for ${event.toolCallId}: ${error instanceof Error ? error.message : \"Unknown error\"}. JSON: ${jsonStr.slice(0, 100)}${jsonStr.length > 100 ? \"...\" : \"\"}`,\n );\n }\n }\n break;\n }\n\n default:\n // Other event types are ignored - only tool call events are tracked\n break;\n }\n }\n\n /**\n * Gets the name and accumulated args for a tool call that is still accumulating.\n * Used by the event loop to get tool state for partial JSON parsing.\n * @param toolCallId - ID of the tool call to look up\n * @returns The tool name and raw accumulated args string, or undefined if not found\n */\n getAccumulatingToolCall(\n toolCallId: string,\n ): { name: string; accumulatedArgs: string } | undefined {\n const toolCall = this.pendingToolCalls.get(toolCallId);\n const args = this.accumulatingArgs.get(toolCallId);\n if (!toolCall || args === undefined) return undefined;\n return { name: toolCall.name, accumulatedArgs: args };\n }\n\n /**\n * Gets tool calls for the given IDs, filtered to only those that exist.\n * @param toolCallIds - IDs of tool calls to retrieve\n * @returns Map of tool call ID to pending tool call\n */\n getToolCallsById(toolCallIds: string[]): Map<string, PendingToolCall> {\n const result = new Map<string, PendingToolCall>();\n for (const id of toolCallIds) {\n const toolCall = this.pendingToolCalls.get(id);\n if (toolCall) {\n result.set(id, toolCall);\n }\n }\n return result;\n }\n\n /**\n * Clears tracked tool calls for the given IDs.\n * @param toolCallIds - IDs of tool calls to clear\n */\n clearToolCalls(toolCallIds: string[]): void {\n for (const id of toolCallIds) {\n this.pendingToolCalls.delete(id);\n this.accumulatingArgs.delete(id);\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-call-tracker.test.d.ts","sourceRoot":"","sources":["../../../src/v1/utils/tool-call-tracker.test.ts"],"names":[],"mappings":""}
|