@assistant-ui/react-ai-sdk 1.3.8 → 1.3.10
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.d.ts.map +1 -1
- package/dist/ui/use-chat/useAISDKRuntime.js +3 -1
- package/dist/ui/use-chat/useAISDKRuntime.js.map +1 -1
- package/dist/ui/utils/convertMessage.d.ts +3 -0
- package/dist/ui/utils/convertMessage.d.ts.map +1 -1
- package/dist/ui/utils/convertMessage.js +33 -1
- package/dist/ui/utils/convertMessage.js.map +1 -1
- package/dist/ui/utils/vercelAttachmentAdapter.js +1 -1
- package/dist/ui/utils/vercelAttachmentAdapter.js.map +1 -1
- package/dist/usage.d.ts +14 -0
- package/dist/usage.d.ts.map +1 -0
- package/dist/usage.js +158 -0
- package/dist/usage.js.map +1 -0
- package/package.json +8 -8
- package/src/index.ts +2 -0
- package/src/ui/use-chat/useAISDKRuntime.ts +5 -1
- package/src/ui/utils/convertMessage.test.ts +72 -0
- package/src/ui/utils/convertMessage.ts +66 -3
- package/src/ui/utils/vercelAttachmentAdapter.ts +1 -1
- package/src/usage.test.ts +137 -0
- package/src/usage.ts +175 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export * from "./ui/index.js";
|
|
2
2
|
export { frontendTools } from "./frontendTools.js";
|
|
3
|
+
export type { ThreadTokenUsage, TokenUsageExtractableMessage } from "./usage.js";
|
|
4
|
+
export { getThreadMessageTokenUsage, useThreadTokenUsage } from "./usage.js";
|
|
3
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8BAAqB;AACrB,OAAO,EAAE,aAAa,EAAE,2BAAwB"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8BAAqB;AACrB,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAChD,YAAY,EAAE,gBAAgB,EAAE,4BAA4B,EAAE,mBAAgB;AAC9E,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,mBAAgB"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8BAAqB;AACrB,OAAO,EAAE,aAAa,EAAE,2BAAwB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8BAAqB;AACrB,OAAO,EAAE,aAAa,EAAE,2BAAwB;AAEhD,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,mBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAISDKRuntime.d.ts","sourceRoot":"","sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEzE,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAQrB,KAAK,aAAa,EAEnB,MAAM,qBAAqB,CAAC;AAgB7B,MAAM,MAAM,6BAA6B,GAAG,CAC1C,UAAU,SAAS,SAAS,GAAG,SAAS,EAExC,OAAO,EAAE,aAAa,KACnB,eAAe,CAAC,UAAU,CAAC,CAAC;AAEjC,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EACL,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,GAAG;QAC/C,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;KAC5C,CAAC,GACF,SAAS,CAAC;IACd,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAChD;;;;;;;OAOG;IACH,4BAA4B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EACtE,aAAa,UAAU,CAAC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,EACnD,sFAIG,mBAAwB,
|
|
1
|
+
{"version":3,"file":"useAISDKRuntime.d.ts","sourceRoot":"","sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEzE,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAQrB,KAAK,aAAa,EAEnB,MAAM,qBAAqB,CAAC;AAgB7B,MAAM,MAAM,6BAA6B,GAAG,CAC1C,UAAU,SAAS,SAAS,GAAG,SAAS,EAExC,OAAO,EAAE,aAAa,KACnB,eAAe,CAAC,UAAU,CAAC,CAAC;AAEjC,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EACL,CAAC,WAAW,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC,GAAG;QAC/C,OAAO,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;KAC5C,CAAC,GACF,SAAS,CAAC;IACd,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAChD;;;;;;;OAOG;IACH,4BAA4B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACpD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,UAAU,SAAS,SAAS,GAAG,SAAS,EACtE,aAAa,UAAU,CAAC,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC,EACnD,sFAIG,mBAAwB,qBAsO5B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useState, useMemo } from "react";
|
|
2
|
+
import { useState, useMemo, useRef } from "react";
|
|
3
3
|
import { isToolUIPart } from "ai";
|
|
4
4
|
import { useExternalStoreRuntime, useRuntimeAdapters, INTERNAL, getExternalStoreMessages, } from "@assistant-ui/react";
|
|
5
5
|
import { sliceMessagesUntil } from "../utils/sliceMessagesUntil.js";
|
|
@@ -13,6 +13,7 @@ import { useStreamingTiming } from "./useStreamingTiming.js";
|
|
|
13
13
|
export const useAISDKRuntime = (chatHelpers, { adapters, toCreateMessage: customToCreateMessage, cancelPendingToolCallsOnSend = true, } = {}) => {
|
|
14
14
|
const contextAdapters = useRuntimeAdapters();
|
|
15
15
|
const [toolStatuses, setToolStatuses] = useState({});
|
|
16
|
+
const toolArgsKeyOrderCacheRef = useRef(new Map());
|
|
16
17
|
const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
|
|
17
18
|
const isRunning = chatHelpers.status === "submitted" ||
|
|
18
19
|
chatHelpers.status === "streaming" ||
|
|
@@ -24,6 +25,7 @@ export const useAISDKRuntime = (chatHelpers, { adapters, toCreateMessage: custom
|
|
|
24
25
|
metadata: useMemo(() => ({
|
|
25
26
|
toolStatuses,
|
|
26
27
|
messageTiming,
|
|
28
|
+
toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,
|
|
27
29
|
...(chatHelpers.error && { error: chatHelpers.error.message }),
|
|
28
30
|
}), [toolStatuses, messageTiming, chatHelpers.error]),
|
|
29
31
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAISDKRuntime.js","sourceRoot":"","sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useAISDKRuntime.js","sourceRoot":"","sources":["../../../src/ui/use-chat/useAISDKRuntime.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EACL,uBAAuB,EAQvB,kBAAkB,EAClB,QAAQ,EAGR,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,uCAAoC;AACjE,OAAO,EAAE,eAAe,EAAE,oCAAiC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,4CAAyC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,kCAA+B;AAC7D,OAAO,EAAE,qBAAqB,EAAE,mCAAgC;AAChE,OAAO,EAEL,oBAAoB,GACrB,0CAAuC;AACxC,OAAO,EACL,kBAAkB,EAClB,2BAA2B,GAC5B,gCAA6B;AAC9B,OAAO,EAAE,kBAAkB,EAAE,gCAA6B;AA0B1D,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,WAAmD,EACnD,EACE,QAAQ,EACR,eAAe,EAAE,qBAAqB,EACtC,4BAA4B,GAAG,IAAI,MACZ,EAAE,EAC3B,EAAE;IACF,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;IAC7C,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAE9C,EAAE,CAAC,CAAC;IACN,MAAM,wBAAwB,GAAG,MAAM,CACrC,IAAI,GAAG,EAAE,CACV,CAAC;IAEF,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CACxD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,WAAW,CAC/B,CAAC;IACF,MAAM,SAAS,GACb,WAAW,CAAC,MAAM,KAAK,WAAW;QAClC,WAAW,CAAC,MAAM,KAAK,WAAW;QAClC,iBAAiB,CAAC;IAEpB,MAAM,aAAa,GAAG,kBAAkB,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAE1E,MAAM,QAAQ,GAAG,qBAAqB,CAAC,iBAAiB,CAAC;QACvD,SAAS;QACT,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,QAAQ,EAAE,OAAO,CACf,GAAG,EAAE,CAAC,CAAC;YACL,YAAY;YACZ,aAAa;YACb,qBAAqB,EAAE,wBAAwB,CAAC,OAAO;YACvD,GAAG,CAAC,WAAW,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;SAC/D,CAAC,EACF,CAAC,YAAY,EAAE,aAAa,EAAE,WAAW,CAAC,KAAK,CAAC,CACjD;KACF,CAAC,CAAC;IAEH,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACnC,IAAI,OAAO;YACT,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,MAAM,eAAe,GAAG,QAAQ,CAAC,kBAAkB,CAAC;QAClD,KAAK,EAAE;YACL,QAAQ;YACR,SAAS;SACV;QACD,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,KAAK;QACjE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;YACpB,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBACvC,WAAW,CAAC,aAAa,CAAC;oBACxB,IAAI,EAAE,OAAO,CAAC,QAAQ;oBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;oBAC9B,MAAM,EAAE,OAAO,CAAC,MAAM;iBACvB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,eAAe;KAChB,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,kBAAkB,CAClC,UAAU,EACV,QAAQ,EAAE,OAAO,IAAI,eAAe,EAAE,OAAO,EAC7C,qBAAqB,CAAC,gBAEF,EACpB,oBAGC,EACD,CAAC,QAAQ,EAAE,EAAE;QACX,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC,CACF,CAAC;IAEF,MAAM,wBAAwB,GAAG,KAAK,IAAI,EAAE;QAC1C,IAAI,CAAC,4BAA4B;YAAE,OAAO;QAE1C,MAAM,eAAe,CAAC,KAAK,EAAE,CAAC;QAE9B,2GAA2G;QAC3G,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,EAAE;YACnC,MAAM,WAAW,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,IAAI,WAAW,EAAE,IAAI,KAAK,WAAW;gBAAE,OAAO,QAAQ,CAAC;YAEvD,IAAI,UAAU,GAAG,KAAK,CAAC;YACvB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC5C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC;oBAAE,OAAO,IAAI,CAAC;gBACrC,IAAI,IAAI,CAAC,KAAK,KAAK,kBAAkB,IAAI,IAAI,CAAC,KAAK,KAAK,cAAc;oBACpE,OAAO,IAAI,CAAC;gBAEd,UAAU,GAAG,IAAI,CAAC;gBAClB,OAAO;oBACL,GAAG,IAAI;oBACP,KAAK,EAAE,cAAuB;oBAC9B,SAAS,EAAE,oDAAoD;iBAChE,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,UAAU;gBAAE,OAAO,QAAQ,CAAC;YACjC,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,WAAW,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,uBAAuB,CAAC;QACtC,SAAS;QACT,QAAQ;QACR,WAAW,EAAE,CAAC,QAAQ,EAAE,EAAE,CACxB,WAAW,CAAC,WAAW,CACrB,QAAQ;aACL,GAAG,CAAC,CAAA,mBAA+B,CAAA,CAAC;aACpC,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,EAAE,CACV;QACH,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE,CACrB,WAAW,CAAC,WAAW,CACrB,QAAQ;aACL,GAAG,CAAC,CAAA,mBAA+B,CAAA,CAAC;aACpC,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,EAAE,CACV;QACH,qBAAqB,EAAE,GAAwC,EAAE;YAC/D,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAEpD,MAAM,gBAAgB,GAAoC,EAAE,CAAC;YAC7D,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;YAEjD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACrC,MAAM,aAAa,GAAG,wBAAwB,CAC5C,IAAI,CAAC,OAAO,CACb,CAAC;gBACF,IAAI,QAAQ,GACV,IAAI,CAAC,QAAQ,IAAI,IAAI;oBACnB,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC;oBACtD,CAAC,CAAC,IAAI,CAAC;gBACX,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;oBACzC,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;oBAC3D,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,YAAyB,CAAC,CAAC;gBACnE,CAAC;gBACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,cAAc,CAAC,GAAG,CAChB,IAAI,CAAC,OAAO,CAAC,EAAE,EACf,oBAAoB,CAAC,KAAK,CACxB,aAAa,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAe,CACtD,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAAwC;gBAClD,QAAQ,EAAE,gBAAgB;aAC3B,CAAC;YAEF,IAAI,QAAQ,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;gBAC5B,MAAM,CAAC,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC;YACzE,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,mBAAmB,EAAE,CAAC,IAAyC,EAAE,EAAE;YACjE,+DAA+D;YAC/D,MAAM,YAAY,GAAG,2BAA2B,CAC9C,qBAAqB,CAAC,gBAAgB,EACtC,IAAI,CACL,CAAC;YAEF,6CAA6C;YAC7C,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACjD,CAAC;QACD,QAAQ,EAAE,KAAK,IAAI,EAAE;YACnB,WAAW,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,eAAe,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC;QACD,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACvB,MAAM,wBAAwB,EAAE,CAAC;YAEjC,MAAM,aAAa,GAAG,CACpB,qBAAqB,IAAI,eAAe,CACzC,CAAa,OAAO,CAAC,CAAC;YACvB,MAAM,WAAW,CAAC,WAAW,CAAC,aAAa,EAAE;gBAC3C,QAAQ,EAAE,OAAO,CAAC,SAAS;aAC5B,CAAC,CAAC;QACL,CAAC;QACD,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACxB,MAAM,WAAW,GAAG,kBAAkB,CACpC,WAAW,CAAC,QAAQ,EACpB,OAAO,CAAC,QAAQ,CACjB,CAAC;YACF,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;YAErC,MAAM,aAAa,GAAG,CACpB,qBAAqB,IAAI,eAAe,CACzC,CAAa,OAAO,CAAC,CAAC;YACvB,MAAM,WAAW,CAAC,WAAW,CAAC,aAAa,EAAE;gBAC3C,QAAQ,EAAE,OAAO,CAAC,SAAS;aAC5B,CAAC,CAAC;QACL,CAAC;QACD,QAAQ,EAAE,KAAK,EAAE,QAAuB,EAAE,MAAM,EAAE,EAAE;YAClD,MAAM,WAAW,GAAG,kBAAkB,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACvE,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;YAErC,MAAM,WAAW,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,eAAe,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;YACnD,IAAI,OAAO,EAAE,CAAC;gBACZ,WAAW,CAAC,aAAa,CAAC;oBACxB,KAAK,EAAE,cAAc;oBACrB,IAAI,EAAE,UAAU;oBAChB,UAAU;oBACV,SAAS,EACP,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;iBAC/D,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,aAAa,CAAC;oBACxB,KAAK,EAAE,kBAAkB;oBACzB,IAAI,EAAE,UAAU;oBAChB,UAAU;oBACV,MAAM,EAAE,MAAM;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,gBAAgB,EAAE,CAAC,OAAO,EAAE,EAAE,CAC5B,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC;QAC7D,QAAQ,EAAE;YACR,WAAW,EAAE,uBAAuB;YACpC,GAAG,eAAe;YAClB,GAAG,QAAQ;SACZ;QACD,SAAS;KACV,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { type UIMessage } from "ai";
|
|
2
2
|
import { type useExternalMessageConverter } from "@assistant-ui/react";
|
|
3
|
+
export type AISDKMessageConverterMetadata = useExternalMessageConverter.Metadata & {
|
|
4
|
+
toolArgsKeyOrderCache?: Map<string, Map<string, string[]>>;
|
|
5
|
+
};
|
|
3
6
|
export declare const AISDKMessageConverter: {
|
|
4
7
|
useThreadMessages: ({ messages, isRunning, joinStrategy, metadata, }: {
|
|
5
8
|
messages: UIMessage<unknown, import("ai").UIDataTypes, import("ai").UITools>[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessage.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/convertMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/D,OAAO,EAOL,KAAK,2BAA2B,EAEjC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"convertMessage.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/convertMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/D,OAAO,EAOL,KAAK,2BAA2B,EAEjC,MAAM,qBAAqB,CAAC;AAI7B,MAAM,MAAM,6BAA6B,GACvC,2BAA2B,CAAC,QAAQ,GAAG;IACrC,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;CAC5D,CAAC;AAmNJ,eAAO,MAAM,qBAAqB;;;;;;;;wHA5MhB,qDAAyB;uHAKpC,qDAAyB;;;CAiQ/B,CAAC"}
|
|
@@ -3,6 +3,34 @@ import { unstable_createMessageConverter, } from "@assistant-ui/react";
|
|
|
3
3
|
function stripClosingDelimiters(json) {
|
|
4
4
|
return json.replace(/[}\]"]+$/, "");
|
|
5
5
|
}
|
|
6
|
+
const hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
|
|
7
|
+
const stabilizeToolArgsValue = (value, path, keyOrderByPath) => {
|
|
8
|
+
if (Array.isArray(value)) {
|
|
9
|
+
return value.map((item, idx) => stabilizeToolArgsValue(item, `${path}[${idx}]`, keyOrderByPath));
|
|
10
|
+
}
|
|
11
|
+
if (value && typeof value === "object") {
|
|
12
|
+
const record = value;
|
|
13
|
+
const currentKeys = Object.keys(record);
|
|
14
|
+
const previousOrder = keyOrderByPath.get(path) ?? [];
|
|
15
|
+
const previousOrderSet = new Set(previousOrder);
|
|
16
|
+
const nextOrder = [
|
|
17
|
+
...previousOrder.filter((key) => hasOwn(record, key)),
|
|
18
|
+
...currentKeys.filter((key) => !previousOrderSet.has(key)),
|
|
19
|
+
];
|
|
20
|
+
keyOrderByPath.set(path, nextOrder);
|
|
21
|
+
return Object.fromEntries(nextOrder.map((key) => [
|
|
22
|
+
key,
|
|
23
|
+
stabilizeToolArgsValue(record[key], `${path}.${key}`, keyOrderByPath),
|
|
24
|
+
]));
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
};
|
|
28
|
+
function stableStringifyToolArgs(keyOrderCache, cacheKey, args) {
|
|
29
|
+
const keyOrderByPath = keyOrderCache?.get(cacheKey) ?? new Map();
|
|
30
|
+
keyOrderCache?.set(cacheKey, keyOrderByPath);
|
|
31
|
+
const stableArgs = stabilizeToolArgsValue(args, "$", keyOrderByPath);
|
|
32
|
+
return JSON.stringify(stableArgs);
|
|
33
|
+
}
|
|
6
34
|
/**
|
|
7
35
|
* Resolves the interrupt fields for a tool call part.
|
|
8
36
|
*
|
|
@@ -56,6 +84,7 @@ function convertParts(message, metadata) {
|
|
|
56
84
|
if (isToolUIPart(part)) {
|
|
57
85
|
const toolName = getToolName(part);
|
|
58
86
|
const toolCallId = part.toolCallId;
|
|
87
|
+
const argsKeyOrderCacheKey = `${message.id}:${toolCallId}`;
|
|
59
88
|
const args = part.input || {};
|
|
60
89
|
let result;
|
|
61
90
|
let isError = false;
|
|
@@ -73,11 +102,14 @@ function convertParts(message, metadata) {
|
|
|
73
102
|
"Tool approval denied",
|
|
74
103
|
};
|
|
75
104
|
}
|
|
76
|
-
let argsText =
|
|
105
|
+
let argsText = stableStringifyToolArgs(metadata.toolArgsKeyOrderCache, argsKeyOrderCacheKey, args);
|
|
77
106
|
if (part.state === "input-streaming") {
|
|
78
107
|
// strip closing delimiters added by the AI SDK's fix-json
|
|
79
108
|
argsText = stripClosingDelimiters(argsText);
|
|
80
109
|
}
|
|
110
|
+
else {
|
|
111
|
+
metadata.toolArgsKeyOrderCache?.delete(argsKeyOrderCacheKey);
|
|
112
|
+
}
|
|
81
113
|
const toolStatus = metadata.toolStatuses?.[toolCallId];
|
|
82
114
|
return {
|
|
83
115
|
type: "tool-call",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertMessage.js","sourceRoot":"","sources":["../../../src/ui/utils/convertMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAkB,MAAM,IAAI,CAAC;AAC/D,OAAO,EACL,+BAA+B,GAQhC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"convertMessage.js","sourceRoot":"","sources":["../../../src/ui/utils/convertMessage.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vercelAttachmentAdapter.js","sourceRoot":"","sources":["../../../src/ui/utils/vercelAttachmentAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,MAAM,cAAc,GAAG,CAAC,IAAU,EAAE,EAAE,CACpC,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IACtC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;IAEhC,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAgB,CAAC,CAAC;IACvD,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE1C,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,uBAAuB,GAAsB;IACxD,MAAM,EACJ,wFAAwF;IAC1F,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,OAAO;YACL,EAAE,EAAE,UAAU,EAAE;YAChB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YACvD,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI;YACJ,WAAW,EAAE,IAAI,CAAC,IAAI;YACtB,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,eAAe,EAAE;SAC7D,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,UAAU;QACnB,OAAO;QACP,OAAO;YACL,GAAG,UAAU;YACb,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,QAAQ,EAAE,UAAU,CAAC,WAAW;
|
|
1
|
+
{"version":3,"file":"vercelAttachmentAdapter.js","sourceRoot":"","sources":["../../../src/ui/utils/vercelAttachmentAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAEhC,MAAM,cAAc,GAAG,CAAC,IAAU,EAAE,EAAE,CACpC,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IACtC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;IAEhC,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAgB,CAAC,CAAC;IACvD,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE1C,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,uBAAuB,GAAsB;IACxD,MAAM,EACJ,wFAAwF;IAC1F,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE;QAChB,OAAO;YACL,EAAE,EAAE,UAAU,EAAE;YAChB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YACvD,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI;YACJ,WAAW,EAAE,IAAI,CAAC,IAAI;YACtB,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,eAAe,EAAE;SAC7D,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,UAAU;QACnB,OAAO;QACP,OAAO;YACL,GAAG,UAAU;YACb,MAAM,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;YAC5B,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,QAAQ,EAAE,UAAU,CAAC,WAAW,IAAI,EAAE;oBACtC,QAAQ,EAAE,UAAU,CAAC,IAAI;oBACzB,IAAI,EAAE,MAAM,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC;iBAC5C;aACF;SACF,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,MAAM;QACV,OAAO;IACT,CAAC;CACF,CAAC"}
|
package/dist/usage.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type ThreadTokenUsage = {
|
|
2
|
+
totalTokens?: number;
|
|
3
|
+
inputTokens?: number;
|
|
4
|
+
outputTokens?: number;
|
|
5
|
+
reasoningTokens?: number;
|
|
6
|
+
cachedInputTokens?: number;
|
|
7
|
+
};
|
|
8
|
+
export interface TokenUsageExtractableMessage {
|
|
9
|
+
role?: string;
|
|
10
|
+
metadata?: unknown;
|
|
11
|
+
}
|
|
12
|
+
export declare function getThreadMessageTokenUsage(message: TokenUsageExtractableMessage | undefined): ThreadTokenUsage | undefined;
|
|
13
|
+
export declare function useThreadTokenUsage(): ThreadTokenUsage | undefined;
|
|
14
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AACF,MAAM,WAAW,4BAA4B;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA8ID,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,4BAA4B,GAAG,SAAS,GAChD,gBAAgB,GAAG,SAAS,CAa9B;AACD,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,SAAS,CAKlE"}
|
package/dist/usage.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { useAuiState } from "@assistant-ui/react";
|
|
2
|
+
function asRecord(value) {
|
|
3
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
4
|
+
return undefined;
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
function asPositiveTokenCount(value) {
|
|
8
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function hasAnyUsageField(parsed) {
|
|
14
|
+
return (parsed.inputTokens !== undefined ||
|
|
15
|
+
parsed.outputTokens !== undefined ||
|
|
16
|
+
parsed.reasoningTokens !== undefined ||
|
|
17
|
+
parsed.cachedInputTokens !== undefined ||
|
|
18
|
+
parsed.totalTokens !== undefined);
|
|
19
|
+
}
|
|
20
|
+
function normalizeUsage(value) {
|
|
21
|
+
const usage = asRecord(value);
|
|
22
|
+
if (!usage)
|
|
23
|
+
return undefined;
|
|
24
|
+
const inputTokens = asPositiveTokenCount(usage.inputTokens);
|
|
25
|
+
const outputTokens = asPositiveTokenCount(usage.outputTokens);
|
|
26
|
+
const reasoningTokens = asPositiveTokenCount(usage.reasoningTokens);
|
|
27
|
+
const cachedInputTokens = asPositiveTokenCount(usage.cachedInputTokens);
|
|
28
|
+
const totalTokens = asPositiveTokenCount(usage.totalTokens);
|
|
29
|
+
const result = {};
|
|
30
|
+
if (inputTokens !== undefined)
|
|
31
|
+
result.inputTokens = inputTokens;
|
|
32
|
+
if (outputTokens !== undefined)
|
|
33
|
+
result.outputTokens = outputTokens;
|
|
34
|
+
if (reasoningTokens !== undefined)
|
|
35
|
+
result.reasoningTokens = reasoningTokens;
|
|
36
|
+
if (cachedInputTokens !== undefined)
|
|
37
|
+
result.cachedInputTokens = cachedInputTokens;
|
|
38
|
+
if (totalTokens !== undefined)
|
|
39
|
+
result.totalTokens = totalTokens;
|
|
40
|
+
if (!hasAnyUsageField(result)) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
45
|
+
function buildUsageResult(parsed) {
|
|
46
|
+
if (!hasAnyUsageField(parsed)) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
const hasBothInputAndOutput = parsed.inputTokens !== undefined && parsed.outputTokens !== undefined;
|
|
50
|
+
const totalTokens = parsed.totalTokens ??
|
|
51
|
+
(hasBothInputAndOutput
|
|
52
|
+
? (parsed.inputTokens ?? 0) + (parsed.outputTokens ?? 0)
|
|
53
|
+
: undefined);
|
|
54
|
+
const result = {};
|
|
55
|
+
if (totalTokens !== undefined)
|
|
56
|
+
result.totalTokens = totalTokens;
|
|
57
|
+
if (parsed.inputTokens !== undefined)
|
|
58
|
+
result.inputTokens = parsed.inputTokens;
|
|
59
|
+
if (parsed.outputTokens !== undefined)
|
|
60
|
+
result.outputTokens = parsed.outputTokens;
|
|
61
|
+
if (parsed.reasoningTokens !== undefined)
|
|
62
|
+
result.reasoningTokens = parsed.reasoningTokens;
|
|
63
|
+
if (parsed.cachedInputTokens !== undefined)
|
|
64
|
+
result.cachedInputTokens = parsed.cachedInputTokens;
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function usageFromSteps(value) {
|
|
68
|
+
const steps = Array.isArray(value) ? value : [];
|
|
69
|
+
let inputTokens = 0;
|
|
70
|
+
let outputTokens = 0;
|
|
71
|
+
let reasoningTokens = 0;
|
|
72
|
+
let cachedInputTokens = 0;
|
|
73
|
+
let totalTokens = 0;
|
|
74
|
+
let hasInput = false;
|
|
75
|
+
let hasOutput = false;
|
|
76
|
+
let hasReasoning = false;
|
|
77
|
+
let hasCachedInput = false;
|
|
78
|
+
let stepsWithUsage = 0;
|
|
79
|
+
let stepsWithComputableTotal = 0;
|
|
80
|
+
for (const step of steps) {
|
|
81
|
+
const usage = normalizeUsage(asRecord(step)?.usage);
|
|
82
|
+
if (!usage)
|
|
83
|
+
continue;
|
|
84
|
+
stepsWithUsage++;
|
|
85
|
+
const stepHasBothInputAndOutput = usage.inputTokens !== undefined && usage.outputTokens !== undefined;
|
|
86
|
+
const stepTotal = usage.totalTokens ??
|
|
87
|
+
(stepHasBothInputAndOutput
|
|
88
|
+
? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0)
|
|
89
|
+
: undefined);
|
|
90
|
+
if (stepTotal !== undefined) {
|
|
91
|
+
totalTokens += stepTotal;
|
|
92
|
+
stepsWithComputableTotal++;
|
|
93
|
+
}
|
|
94
|
+
if (usage.inputTokens !== undefined) {
|
|
95
|
+
inputTokens += usage.inputTokens;
|
|
96
|
+
hasInput = true;
|
|
97
|
+
}
|
|
98
|
+
if (usage.outputTokens !== undefined) {
|
|
99
|
+
outputTokens += usage.outputTokens;
|
|
100
|
+
hasOutput = true;
|
|
101
|
+
}
|
|
102
|
+
if (usage.reasoningTokens !== undefined) {
|
|
103
|
+
reasoningTokens += usage.reasoningTokens;
|
|
104
|
+
hasReasoning = true;
|
|
105
|
+
}
|
|
106
|
+
if (usage.cachedInputTokens !== undefined) {
|
|
107
|
+
cachedInputTokens += usage.cachedInputTokens;
|
|
108
|
+
hasCachedInput = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (stepsWithUsage === 0)
|
|
112
|
+
return undefined;
|
|
113
|
+
const parsed = {};
|
|
114
|
+
if (hasInput)
|
|
115
|
+
parsed.inputTokens = inputTokens;
|
|
116
|
+
if (hasOutput)
|
|
117
|
+
parsed.outputTokens = outputTokens;
|
|
118
|
+
if (hasReasoning)
|
|
119
|
+
parsed.reasoningTokens = reasoningTokens;
|
|
120
|
+
if (hasCachedInput)
|
|
121
|
+
parsed.cachedInputTokens = cachedInputTokens;
|
|
122
|
+
if (stepsWithComputableTotal === stepsWithUsage) {
|
|
123
|
+
parsed.totalTokens = totalTokens;
|
|
124
|
+
}
|
|
125
|
+
const result = {};
|
|
126
|
+
if (parsed.totalTokens !== undefined)
|
|
127
|
+
result.totalTokens = parsed.totalTokens;
|
|
128
|
+
if (parsed.inputTokens !== undefined)
|
|
129
|
+
result.inputTokens = parsed.inputTokens;
|
|
130
|
+
if (parsed.outputTokens !== undefined)
|
|
131
|
+
result.outputTokens = parsed.outputTokens;
|
|
132
|
+
if (parsed.reasoningTokens !== undefined)
|
|
133
|
+
result.reasoningTokens = parsed.reasoningTokens;
|
|
134
|
+
if (parsed.cachedInputTokens !== undefined)
|
|
135
|
+
result.cachedInputTokens = parsed.cachedInputTokens;
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
export function getThreadMessageTokenUsage(message) {
|
|
139
|
+
if (!message || message.role !== "assistant")
|
|
140
|
+
return undefined;
|
|
141
|
+
const metadata = asRecord(message.metadata);
|
|
142
|
+
if (!metadata)
|
|
143
|
+
return undefined;
|
|
144
|
+
const topLevelUsage = normalizeUsage(metadata.usage);
|
|
145
|
+
if (topLevelUsage) {
|
|
146
|
+
return buildUsageResult(topLevelUsage);
|
|
147
|
+
}
|
|
148
|
+
const legacyUsage = normalizeUsage(asRecord(metadata.custom)?.usage);
|
|
149
|
+
if (legacyUsage) {
|
|
150
|
+
return buildUsageResult(legacyUsage);
|
|
151
|
+
}
|
|
152
|
+
return usageFromSteps(metadata.steps);
|
|
153
|
+
}
|
|
154
|
+
export function useThreadTokenUsage() {
|
|
155
|
+
const lastAssistant = useAuiState((s) => s.thread.messages.findLast((m) => m.role === "assistant"));
|
|
156
|
+
return getThreadMessageTokenUsage(lastAssistant);
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../src/usage.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-ai-sdk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.10",
|
|
4
4
|
"description": "Vercel AI SDK adapter for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai-sdk",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
],
|
|
32
32
|
"sideEffects": false,
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ai-sdk/react": "^3.0.
|
|
35
|
-
"ai": "^6.0.
|
|
34
|
+
"@ai-sdk/react": "^3.0.100",
|
|
35
|
+
"ai": "^6.0.98",
|
|
36
36
|
"zod": "^4.3.6"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@assistant-ui/react": "^0.12.
|
|
39
|
+
"@assistant-ui/react": "^0.12.14",
|
|
40
40
|
"@types/react": "*",
|
|
41
41
|
"assistant-cloud": "*",
|
|
42
42
|
"react": "^18 || ^19"
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@testing-library/react": "^16.3.2",
|
|
54
54
|
"@types/json-schema": "^7.0.15",
|
|
55
|
-
"@types/react": "^19.2.
|
|
55
|
+
"@types/react": "^19.2.14",
|
|
56
56
|
"@types/react-dom": "^19.2.3",
|
|
57
|
-
"jsdom": "^28.
|
|
57
|
+
"jsdom": "^28.1.0",
|
|
58
58
|
"react": "^19.2.4",
|
|
59
59
|
"vitest": "^4.0.18",
|
|
60
|
-
"@assistant-ui/react": "0.12.
|
|
60
|
+
"@assistant-ui/react": "0.12.14",
|
|
61
61
|
"@assistant-ui/x-buildutils": "0.0.1",
|
|
62
|
-
"assistant-stream": "0.3.
|
|
62
|
+
"assistant-stream": "0.3.4"
|
|
63
63
|
},
|
|
64
64
|
"publishConfig": {
|
|
65
65
|
"access": "public",
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useState, useMemo } from "react";
|
|
3
|
+
import { useState, useMemo, useRef } from "react";
|
|
4
4
|
import type { UIMessage, useChat, CreateUIMessage } from "@ai-sdk/react";
|
|
5
5
|
import { isToolUIPart } from "ai";
|
|
6
6
|
import {
|
|
@@ -69,6 +69,9 @@ export const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
|
69
69
|
const [toolStatuses, setToolStatuses] = useState<
|
|
70
70
|
Record<string, ToolExecutionStatus>
|
|
71
71
|
>({});
|
|
72
|
+
const toolArgsKeyOrderCacheRef = useRef<Map<string, Map<string, string[]>>>(
|
|
73
|
+
new Map(),
|
|
74
|
+
);
|
|
72
75
|
|
|
73
76
|
const hasExecutingTools = Object.values(toolStatuses).some(
|
|
74
77
|
(s) => s?.type === "executing",
|
|
@@ -87,6 +90,7 @@ export const useAISDKRuntime = <UI_MESSAGE extends UIMessage = UIMessage>(
|
|
|
87
90
|
() => ({
|
|
88
91
|
toolStatuses,
|
|
89
92
|
messageTiming,
|
|
93
|
+
toolArgsKeyOrderCache: toolArgsKeyOrderCacheRef.current,
|
|
90
94
|
...(chatHelpers.error && { error: chatHelpers.error.message }),
|
|
91
95
|
}),
|
|
92
96
|
[toolStatuses, messageTiming, chatHelpers.error],
|
|
@@ -122,4 +122,76 @@ describe("AISDKMessageConverter", () => {
|
|
|
122
122
|
);
|
|
123
123
|
expect(toolCall?.argsText).toBe('{"city":"NYC');
|
|
124
124
|
});
|
|
125
|
+
|
|
126
|
+
it("keeps observed key order from streaming snapshots for final tool args", () => {
|
|
127
|
+
const metadata = {
|
|
128
|
+
toolArgsKeyOrderCache: new Map<string, Map<string, string[]>>(),
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const streaming = AISDKMessageConverter.toThreadMessages(
|
|
132
|
+
[
|
|
133
|
+
{
|
|
134
|
+
id: "a1",
|
|
135
|
+
role: "assistant",
|
|
136
|
+
parts: [
|
|
137
|
+
{
|
|
138
|
+
type: "tool-stocks",
|
|
139
|
+
toolCallId: "tc-order-1",
|
|
140
|
+
state: "input-streaming",
|
|
141
|
+
input: {
|
|
142
|
+
type: "high_stock_model",
|
|
143
|
+
limit: 5,
|
|
144
|
+
filters: {
|
|
145
|
+
region: "us",
|
|
146
|
+
sector: "tech",
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
} as any,
|
|
152
|
+
],
|
|
153
|
+
false,
|
|
154
|
+
metadata,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
const streamingToolCall = streaming[0]?.content.find(
|
|
158
|
+
(part): part is any => part.type === "tool-call",
|
|
159
|
+
);
|
|
160
|
+
expect(streamingToolCall?.argsText).toBe(
|
|
161
|
+
'{"type":"high_stock_model","limit":5,"filters":{"region":"us","sector":"tech',
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
const final = AISDKMessageConverter.toThreadMessages(
|
|
165
|
+
[
|
|
166
|
+
{
|
|
167
|
+
id: "a1",
|
|
168
|
+
role: "assistant",
|
|
169
|
+
parts: [
|
|
170
|
+
{
|
|
171
|
+
type: "tool-stocks",
|
|
172
|
+
toolCallId: "tc-order-1",
|
|
173
|
+
state: "input-available",
|
|
174
|
+
input: {
|
|
175
|
+
filters: {
|
|
176
|
+
sector: "tech",
|
|
177
|
+
region: "us",
|
|
178
|
+
},
|
|
179
|
+
limit: 5,
|
|
180
|
+
type: "high_stock_model",
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
} as any,
|
|
185
|
+
],
|
|
186
|
+
false,
|
|
187
|
+
metadata,
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const finalToolCall = final[0]?.content.find(
|
|
191
|
+
(part): part is any => part.type === "tool-call",
|
|
192
|
+
);
|
|
193
|
+
expect(finalToolCall?.argsText).toBe(
|
|
194
|
+
'{"type":"high_stock_model","limit":5,"filters":{"region":"us","sector":"tech"}}',
|
|
195
|
+
);
|
|
196
|
+
});
|
|
125
197
|
});
|
|
@@ -12,11 +12,67 @@ import {
|
|
|
12
12
|
import type { ReadonlyJSONObject } from "assistant-stream/utils";
|
|
13
13
|
|
|
14
14
|
type MessageMetadata = ThreadMessageLike["metadata"];
|
|
15
|
+
export type AISDKMessageConverterMetadata =
|
|
16
|
+
useExternalMessageConverter.Metadata & {
|
|
17
|
+
toolArgsKeyOrderCache?: Map<string, Map<string, string[]>>;
|
|
18
|
+
};
|
|
15
19
|
|
|
16
20
|
function stripClosingDelimiters(json: string): string {
|
|
17
21
|
return json.replace(/[}\]"]+$/, "");
|
|
18
22
|
}
|
|
19
23
|
|
|
24
|
+
const hasOwn = (value: object, key: string) =>
|
|
25
|
+
Object.prototype.hasOwnProperty.call(value, key);
|
|
26
|
+
|
|
27
|
+
const stabilizeToolArgsValue = (
|
|
28
|
+
value: unknown,
|
|
29
|
+
path: string,
|
|
30
|
+
keyOrderByPath: Map<string, string[]>,
|
|
31
|
+
): unknown => {
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
return value.map((item, idx) =>
|
|
34
|
+
stabilizeToolArgsValue(item, `${path}[${idx}]`, keyOrderByPath),
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (value && typeof value === "object") {
|
|
39
|
+
const record = value as Record<string, unknown>;
|
|
40
|
+
const currentKeys = Object.keys(record);
|
|
41
|
+
const previousOrder = keyOrderByPath.get(path) ?? [];
|
|
42
|
+
const previousOrderSet = new Set(previousOrder);
|
|
43
|
+
const nextOrder = [
|
|
44
|
+
...previousOrder.filter((key) => hasOwn(record, key)),
|
|
45
|
+
...currentKeys.filter((key) => !previousOrderSet.has(key)),
|
|
46
|
+
];
|
|
47
|
+
keyOrderByPath.set(path, nextOrder);
|
|
48
|
+
|
|
49
|
+
return Object.fromEntries(
|
|
50
|
+
nextOrder.map((key) => [
|
|
51
|
+
key,
|
|
52
|
+
stabilizeToolArgsValue(record[key], `${path}.${key}`, keyOrderByPath),
|
|
53
|
+
]),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return value;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
function stableStringifyToolArgs(
|
|
61
|
+
keyOrderCache: Map<string, Map<string, string[]>> | undefined,
|
|
62
|
+
cacheKey: string,
|
|
63
|
+
args: ReadonlyJSONObject,
|
|
64
|
+
): string {
|
|
65
|
+
const keyOrderByPath = keyOrderCache?.get(cacheKey) ?? new Map();
|
|
66
|
+
keyOrderCache?.set(cacheKey, keyOrderByPath);
|
|
67
|
+
|
|
68
|
+
const stableArgs = stabilizeToolArgsValue(
|
|
69
|
+
args,
|
|
70
|
+
"$",
|
|
71
|
+
keyOrderByPath,
|
|
72
|
+
) as ReadonlyJSONObject;
|
|
73
|
+
return JSON.stringify(stableArgs);
|
|
74
|
+
}
|
|
75
|
+
|
|
20
76
|
/**
|
|
21
77
|
* Resolves the interrupt fields for a tool call part.
|
|
22
78
|
*
|
|
@@ -58,7 +114,7 @@ type MessageContent = Exclude<ThreadMessageLike["content"], string>;
|
|
|
58
114
|
|
|
59
115
|
function convertParts(
|
|
60
116
|
message: UIMessage,
|
|
61
|
-
metadata:
|
|
117
|
+
metadata: AISDKMessageConverterMetadata,
|
|
62
118
|
): MessageContent {
|
|
63
119
|
if (!message.parts || message.parts.length === 0) {
|
|
64
120
|
return [];
|
|
@@ -84,6 +140,7 @@ function convertParts(
|
|
|
84
140
|
if (isToolUIPart(part)) {
|
|
85
141
|
const toolName = getToolName(part);
|
|
86
142
|
const toolCallId = part.toolCallId;
|
|
143
|
+
const argsKeyOrderCacheKey = `${message.id}:${toolCallId}`;
|
|
87
144
|
const args: ReadonlyJSONObject =
|
|
88
145
|
(part.input as ReadonlyJSONObject) || {};
|
|
89
146
|
|
|
@@ -104,10 +161,16 @@ function convertParts(
|
|
|
104
161
|
};
|
|
105
162
|
}
|
|
106
163
|
|
|
107
|
-
let argsText =
|
|
164
|
+
let argsText = stableStringifyToolArgs(
|
|
165
|
+
metadata.toolArgsKeyOrderCache,
|
|
166
|
+
argsKeyOrderCacheKey,
|
|
167
|
+
args,
|
|
168
|
+
);
|
|
108
169
|
if (part.state === "input-streaming") {
|
|
109
170
|
// strip closing delimiters added by the AI SDK's fix-json
|
|
110
171
|
argsText = stripClosingDelimiters(argsText);
|
|
172
|
+
} else {
|
|
173
|
+
metadata.toolArgsKeyOrderCache?.delete(argsKeyOrderCacheKey);
|
|
111
174
|
}
|
|
112
175
|
|
|
113
176
|
const toolStatus = metadata.toolStatuses?.[toolCallId];
|
|
@@ -164,7 +227,7 @@ function convertParts(
|
|
|
164
227
|
}
|
|
165
228
|
|
|
166
229
|
export const AISDKMessageConverter = unstable_createMessageConverter(
|
|
167
|
-
(message: UIMessage, metadata:
|
|
230
|
+
(message: UIMessage, metadata: AISDKMessageConverterMetadata) => {
|
|
168
231
|
const createdAt = new Date();
|
|
169
232
|
const content = convertParts(message, metadata);
|
|
170
233
|
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { getThreadMessageTokenUsage } from "./usage";
|
|
3
|
+
|
|
4
|
+
function msg(metadata: unknown): { role: "assistant"; metadata: unknown } {
|
|
5
|
+
return {
|
|
6
|
+
role: "assistant",
|
|
7
|
+
metadata,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
describe("getThreadMessageTokenUsage", () => {
|
|
12
|
+
it("does not double-count reasoning/cached in fallback totalTokens", () => {
|
|
13
|
+
const usage = getThreadMessageTokenUsage(
|
|
14
|
+
msg({
|
|
15
|
+
usage: {
|
|
16
|
+
inputTokens: 4,
|
|
17
|
+
outputTokens: 6,
|
|
18
|
+
reasoningTokens: 9,
|
|
19
|
+
cachedInputTokens: 3,
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// totalTokens = input + output only; reasoning/cached are detail fields
|
|
25
|
+
expect(usage).toEqual({
|
|
26
|
+
totalTokens: 10,
|
|
27
|
+
inputTokens: 4,
|
|
28
|
+
outputTokens: 6,
|
|
29
|
+
reasoningTokens: 9,
|
|
30
|
+
cachedInputTokens: 3,
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("does not fabricate zero splits when only totalTokens is present", () => {
|
|
35
|
+
const usage = getThreadMessageTokenUsage(
|
|
36
|
+
msg({ usage: { totalTokens: 12 } }),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
expect(usage).toEqual({ totalTokens: 12 });
|
|
40
|
+
expect(usage).not.toHaveProperty("inputTokens");
|
|
41
|
+
expect(usage).not.toHaveProperty("outputTokens");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("retains partial usage when only inputTokens is present", () => {
|
|
45
|
+
const usage = getThreadMessageTokenUsage(
|
|
46
|
+
msg({ usage: { inputTokens: 10 } }),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(usage).toEqual({ inputTokens: 10 });
|
|
50
|
+
expect(usage).not.toHaveProperty("totalTokens");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("retains partial usage when only outputTokens is present", () => {
|
|
54
|
+
const usage = getThreadMessageTokenUsage(
|
|
55
|
+
msg({ usage: { outputTokens: 4 } }),
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
expect(usage).toEqual({ outputTokens: 4 });
|
|
59
|
+
expect(usage).not.toHaveProperty("totalTokens");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("retains detail-only usage when only reasoning/cached tokens are present", () => {
|
|
63
|
+
const usage = getThreadMessageTokenUsage(
|
|
64
|
+
msg({ usage: { reasoningTokens: 7, cachedInputTokens: 2 } }),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
expect(usage).toEqual({ reasoningTokens: 7, cachedInputTokens: 2 });
|
|
68
|
+
expect(usage).not.toHaveProperty("totalTokens");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("aggregates multi-step usage without inflating totals", () => {
|
|
72
|
+
const usage = getThreadMessageTokenUsage(
|
|
73
|
+
msg({
|
|
74
|
+
steps: [
|
|
75
|
+
{ usage: { inputTokens: 3, outputTokens: 2, reasoningTokens: 11 } },
|
|
76
|
+
{ usage: { inputTokens: 4, outputTokens: 1, reasoningTokens: 13 } },
|
|
77
|
+
],
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
expect(usage).toEqual({
|
|
82
|
+
totalTokens: 10,
|
|
83
|
+
inputTokens: 7,
|
|
84
|
+
outputTokens: 3,
|
|
85
|
+
reasoningTokens: 24,
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("omits totalTokens if any step lacks a computable total", () => {
|
|
90
|
+
const usage = getThreadMessageTokenUsage(
|
|
91
|
+
msg({
|
|
92
|
+
steps: [
|
|
93
|
+
{ usage: { inputTokens: 5, outputTokens: 5 } }, // total = 10
|
|
94
|
+
{ usage: { reasoningTokens: 10 } }, // total = undefined
|
|
95
|
+
],
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// Sums known partials but omits the invalid total
|
|
100
|
+
expect(usage).toEqual({
|
|
101
|
+
inputTokens: 5,
|
|
102
|
+
outputTokens: 5,
|
|
103
|
+
reasoningTokens: 10,
|
|
104
|
+
});
|
|
105
|
+
expect(usage).not.toHaveProperty("totalTokens");
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("aggregates totalTokens if all steps have a computable total", () => {
|
|
109
|
+
const usage = getThreadMessageTokenUsage(
|
|
110
|
+
msg({
|
|
111
|
+
steps: [
|
|
112
|
+
{ usage: { inputTokens: 5, outputTokens: 5 } }, // implicit total = 10
|
|
113
|
+
{ usage: { totalTokens: 15 } }, // explicit total = 15
|
|
114
|
+
],
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
expect(usage).toEqual({
|
|
119
|
+
totalTokens: 25,
|
|
120
|
+
inputTokens: 5,
|
|
121
|
+
outputTokens: 5,
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("omits totalTokens when one step has only total and another has only input", () => {
|
|
126
|
+
const usage = getThreadMessageTokenUsage(
|
|
127
|
+
msg({
|
|
128
|
+
steps: [{ usage: { totalTokens: 10 } }, { usage: { inputTokens: 3 } }],
|
|
129
|
+
}),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
expect(usage).toEqual({
|
|
133
|
+
inputTokens: 3,
|
|
134
|
+
});
|
|
135
|
+
expect(usage).not.toHaveProperty("totalTokens");
|
|
136
|
+
});
|
|
137
|
+
});
|
package/src/usage.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { useAuiState } from "@assistant-ui/react";
|
|
2
|
+
export type ThreadTokenUsage = {
|
|
3
|
+
totalTokens?: number;
|
|
4
|
+
inputTokens?: number;
|
|
5
|
+
outputTokens?: number;
|
|
6
|
+
reasoningTokens?: number;
|
|
7
|
+
cachedInputTokens?: number;
|
|
8
|
+
};
|
|
9
|
+
export interface TokenUsageExtractableMessage {
|
|
10
|
+
role?: string;
|
|
11
|
+
metadata?: unknown;
|
|
12
|
+
}
|
|
13
|
+
// Internal types for parsing
|
|
14
|
+
type UsageRecord = Record<string, unknown>;
|
|
15
|
+
function asRecord(value: unknown): UsageRecord | undefined {
|
|
16
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
17
|
+
return undefined;
|
|
18
|
+
return value as UsageRecord;
|
|
19
|
+
}
|
|
20
|
+
function asPositiveTokenCount(value: unknown): number | undefined {
|
|
21
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
// Internal type that makes everything optional for the intermediate parsing steps
|
|
27
|
+
type ParsedUsage = {
|
|
28
|
+
inputTokens?: number;
|
|
29
|
+
outputTokens?: number;
|
|
30
|
+
reasoningTokens?: number;
|
|
31
|
+
cachedInputTokens?: number;
|
|
32
|
+
totalTokens?: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
function hasAnyUsageField(parsed: ParsedUsage): boolean {
|
|
36
|
+
return (
|
|
37
|
+
parsed.inputTokens !== undefined ||
|
|
38
|
+
parsed.outputTokens !== undefined ||
|
|
39
|
+
parsed.reasoningTokens !== undefined ||
|
|
40
|
+
parsed.cachedInputTokens !== undefined ||
|
|
41
|
+
parsed.totalTokens !== undefined
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function normalizeUsage(value: unknown): ParsedUsage | undefined {
|
|
46
|
+
const usage = asRecord(value);
|
|
47
|
+
if (!usage) return undefined;
|
|
48
|
+
const inputTokens = asPositiveTokenCount(usage.inputTokens);
|
|
49
|
+
const outputTokens = asPositiveTokenCount(usage.outputTokens);
|
|
50
|
+
const reasoningTokens = asPositiveTokenCount(usage.reasoningTokens);
|
|
51
|
+
const cachedInputTokens = asPositiveTokenCount(usage.cachedInputTokens);
|
|
52
|
+
const totalTokens = asPositiveTokenCount(usage.totalTokens);
|
|
53
|
+
const result: ParsedUsage = {};
|
|
54
|
+
if (inputTokens !== undefined) result.inputTokens = inputTokens;
|
|
55
|
+
if (outputTokens !== undefined) result.outputTokens = outputTokens;
|
|
56
|
+
if (reasoningTokens !== undefined) result.reasoningTokens = reasoningTokens;
|
|
57
|
+
if (cachedInputTokens !== undefined)
|
|
58
|
+
result.cachedInputTokens = cachedInputTokens;
|
|
59
|
+
if (totalTokens !== undefined) result.totalTokens = totalTokens;
|
|
60
|
+
|
|
61
|
+
if (!hasAnyUsageField(result)) {
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
function buildUsageResult(parsed: ParsedUsage): ThreadTokenUsage | undefined {
|
|
68
|
+
if (!hasAnyUsageField(parsed)) {
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
const hasBothInputAndOutput =
|
|
72
|
+
parsed.inputTokens !== undefined && parsed.outputTokens !== undefined;
|
|
73
|
+
const totalTokens =
|
|
74
|
+
parsed.totalTokens ??
|
|
75
|
+
(hasBothInputAndOutput
|
|
76
|
+
? (parsed.inputTokens ?? 0) + (parsed.outputTokens ?? 0)
|
|
77
|
+
: undefined);
|
|
78
|
+
const result: ThreadTokenUsage = {};
|
|
79
|
+
if (totalTokens !== undefined) result.totalTokens = totalTokens;
|
|
80
|
+
if (parsed.inputTokens !== undefined) result.inputTokens = parsed.inputTokens;
|
|
81
|
+
if (parsed.outputTokens !== undefined)
|
|
82
|
+
result.outputTokens = parsed.outputTokens;
|
|
83
|
+
if (parsed.reasoningTokens !== undefined)
|
|
84
|
+
result.reasoningTokens = parsed.reasoningTokens;
|
|
85
|
+
if (parsed.cachedInputTokens !== undefined)
|
|
86
|
+
result.cachedInputTokens = parsed.cachedInputTokens;
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
function usageFromSteps(value: unknown): ThreadTokenUsage | undefined {
|
|
90
|
+
const steps = Array.isArray(value) ? value : [];
|
|
91
|
+
let inputTokens = 0;
|
|
92
|
+
let outputTokens = 0;
|
|
93
|
+
let reasoningTokens = 0;
|
|
94
|
+
let cachedInputTokens = 0;
|
|
95
|
+
let totalTokens = 0;
|
|
96
|
+
let hasInput = false;
|
|
97
|
+
let hasOutput = false;
|
|
98
|
+
let hasReasoning = false;
|
|
99
|
+
let hasCachedInput = false;
|
|
100
|
+
let stepsWithUsage = 0;
|
|
101
|
+
let stepsWithComputableTotal = 0;
|
|
102
|
+
for (const step of steps) {
|
|
103
|
+
const usage = normalizeUsage(asRecord(step)?.usage);
|
|
104
|
+
if (!usage) continue;
|
|
105
|
+
stepsWithUsage++;
|
|
106
|
+
const stepHasBothInputAndOutput =
|
|
107
|
+
usage.inputTokens !== undefined && usage.outputTokens !== undefined;
|
|
108
|
+
const stepTotal =
|
|
109
|
+
usage.totalTokens ??
|
|
110
|
+
(stepHasBothInputAndOutput
|
|
111
|
+
? (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0)
|
|
112
|
+
: undefined);
|
|
113
|
+
if (stepTotal !== undefined) {
|
|
114
|
+
totalTokens += stepTotal;
|
|
115
|
+
stepsWithComputableTotal++;
|
|
116
|
+
}
|
|
117
|
+
if (usage.inputTokens !== undefined) {
|
|
118
|
+
inputTokens += usage.inputTokens;
|
|
119
|
+
hasInput = true;
|
|
120
|
+
}
|
|
121
|
+
if (usage.outputTokens !== undefined) {
|
|
122
|
+
outputTokens += usage.outputTokens;
|
|
123
|
+
hasOutput = true;
|
|
124
|
+
}
|
|
125
|
+
if (usage.reasoningTokens !== undefined) {
|
|
126
|
+
reasoningTokens += usage.reasoningTokens;
|
|
127
|
+
hasReasoning = true;
|
|
128
|
+
}
|
|
129
|
+
if (usage.cachedInputTokens !== undefined) {
|
|
130
|
+
cachedInputTokens += usage.cachedInputTokens;
|
|
131
|
+
hasCachedInput = true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (stepsWithUsage === 0) return undefined;
|
|
135
|
+
const parsed: ParsedUsage = {};
|
|
136
|
+
if (hasInput) parsed.inputTokens = inputTokens;
|
|
137
|
+
if (hasOutput) parsed.outputTokens = outputTokens;
|
|
138
|
+
if (hasReasoning) parsed.reasoningTokens = reasoningTokens;
|
|
139
|
+
if (hasCachedInput) parsed.cachedInputTokens = cachedInputTokens;
|
|
140
|
+
if (stepsWithComputableTotal === stepsWithUsage) {
|
|
141
|
+
parsed.totalTokens = totalTokens;
|
|
142
|
+
}
|
|
143
|
+
const result: ThreadTokenUsage = {};
|
|
144
|
+
if (parsed.totalTokens !== undefined) result.totalTokens = parsed.totalTokens;
|
|
145
|
+
if (parsed.inputTokens !== undefined) result.inputTokens = parsed.inputTokens;
|
|
146
|
+
if (parsed.outputTokens !== undefined)
|
|
147
|
+
result.outputTokens = parsed.outputTokens;
|
|
148
|
+
if (parsed.reasoningTokens !== undefined)
|
|
149
|
+
result.reasoningTokens = parsed.reasoningTokens;
|
|
150
|
+
if (parsed.cachedInputTokens !== undefined)
|
|
151
|
+
result.cachedInputTokens = parsed.cachedInputTokens;
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
export function getThreadMessageTokenUsage(
|
|
155
|
+
message: TokenUsageExtractableMessage | undefined,
|
|
156
|
+
): ThreadTokenUsage | undefined {
|
|
157
|
+
if (!message || message.role !== "assistant") return undefined;
|
|
158
|
+
const metadata = asRecord(message.metadata);
|
|
159
|
+
if (!metadata) return undefined;
|
|
160
|
+
const topLevelUsage = normalizeUsage(metadata.usage);
|
|
161
|
+
if (topLevelUsage) {
|
|
162
|
+
return buildUsageResult(topLevelUsage);
|
|
163
|
+
}
|
|
164
|
+
const legacyUsage = normalizeUsage(asRecord(metadata.custom)?.usage);
|
|
165
|
+
if (legacyUsage) {
|
|
166
|
+
return buildUsageResult(legacyUsage);
|
|
167
|
+
}
|
|
168
|
+
return usageFromSteps(metadata.steps);
|
|
169
|
+
}
|
|
170
|
+
export function useThreadTokenUsage(): ThreadTokenUsage | undefined {
|
|
171
|
+
const lastAssistant = useAuiState((s) =>
|
|
172
|
+
s.thread.messages.findLast((m) => m.role === "assistant"),
|
|
173
|
+
);
|
|
174
|
+
return getThreadMessageTokenUsage(lastAssistant);
|
|
175
|
+
}
|