assistant-cloud 0.1.27 → 0.1.29
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 +42 -0
- package/dist/AssistantCloud.d.ts +15 -11
- package/dist/AssistantCloud.d.ts.map +1 -1
- package/dist/AssistantCloud.js +24 -24
- package/dist/AssistantCloud.js.map +1 -1
- package/dist/AssistantCloudAPI.d.ts +46 -42
- package/dist/AssistantCloudAPI.d.ts.map +1 -1
- package/dist/AssistantCloudAPI.js +66 -79
- package/dist/AssistantCloudAPI.js.map +1 -1
- package/dist/AssistantCloudAuthStrategy.d.ts +28 -25
- package/dist/AssistantCloudAuthStrategy.d.ts.map +1 -1
- package/dist/AssistantCloudAuthStrategy.js +98 -135
- package/dist/AssistantCloudAuthStrategy.js.map +1 -1
- package/dist/AssistantCloudAuthTokens.d.ts +10 -7
- package/dist/AssistantCloudAuthTokens.d.ts.map +1 -1
- package/dist/AssistantCloudAuthTokens.js +13 -9
- package/dist/AssistantCloudAuthTokens.js.map +1 -1
- package/dist/AssistantCloudFiles.d.ts +20 -17
- package/dist/AssistantCloudFiles.d.ts.map +1 -1
- package/dist/AssistantCloudFiles.js +22 -18
- package/dist/AssistantCloudFiles.js.map +1 -1
- package/dist/AssistantCloudRuns.d.ts +53 -50
- package/dist/AssistantCloudRuns.d.ts.map +1 -1
- package/dist/AssistantCloudRuns.js +42 -38
- package/dist/AssistantCloudRuns.js.map +1 -1
- package/dist/AssistantCloudThreadMessages.d.ts +27 -24
- package/dist/AssistantCloudThreadMessages.d.ts.map +1 -1
- package/dist/AssistantCloudThreadMessages.js +25 -15
- package/dist/AssistantCloudThreadMessages.js.map +1 -1
- package/dist/AssistantCloudThreads.d.ts +37 -34
- package/dist/AssistantCloudThreads.d.ts.map +1 -1
- package/dist/AssistantCloudThreads.js +33 -28
- package/dist/AssistantCloudThreads.js.map +1 -1
- package/dist/CloudMessagePersistence.d.ts +49 -44
- package/dist/CloudMessagePersistence.d.ts.map +1 -1
- package/dist/CloudMessagePersistence.js +90 -101
- package/dist/CloudMessagePersistence.js.map +1 -1
- package/dist/FormattedCloudPersistence.d.ts +40 -36
- package/dist/FormattedCloudPersistence.d.ts.map +1 -1
- package/dist/FormattedCloudPersistence.js +32 -36
- package/dist/FormattedCloudPersistence.js.map +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +5 -5
- package/dist/instrumentMcpSampling.d.ts +39 -36
- package/dist/instrumentMcpSampling.d.ts.map +1 -1
- package/dist/instrumentMcpSampling.js +61 -68
- package/dist/instrumentMcpSampling.js.map +1 -1
- package/dist/tests/setup.d.ts +1 -2
- package/dist/tests/setup.js +3 -4
- package/dist/tests/setup.js.map +1 -1
- package/package.json +5 -5
- package/src/AssistantCloudAPI.ts +4 -1
- package/src/tests/AssistantCloudAPI.test.ts +42 -0
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/tests/setup.d.ts.map +0 -1
|
@@ -1,73 +1,66 @@
|
|
|
1
|
+
//#region src/instrumentMcpSampling.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
...(outputTokens != null ? { output_tokens: outputTokens } : undefined),
|
|
40
|
-
...(reasoningTokens != null
|
|
41
|
-
? { reasoning_tokens: reasoningTokens }
|
|
42
|
-
: undefined),
|
|
43
|
-
...(cachedInputTokens != null
|
|
44
|
-
? { cached_input_tokens: cachedInputTokens }
|
|
45
|
-
: undefined),
|
|
46
|
-
duration_ms: durationMs,
|
|
47
|
-
});
|
|
48
|
-
return response;
|
|
49
|
-
};
|
|
3
|
+
* Wraps an MCP sampling handler to intercept and measure sampling calls.
|
|
4
|
+
*
|
|
5
|
+
* @param handler - The original sampling handler from the MCP client
|
|
6
|
+
* @param onSamplingCall - Callback invoked with metrics for each sampling call
|
|
7
|
+
* @returns A wrapped handler that transparently captures sampling metrics
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const samplingCalls: SamplingCallData[] = [];
|
|
12
|
+
* const wrapped = wrapSamplingHandler(
|
|
13
|
+
* originalHandler,
|
|
14
|
+
* (data) => samplingCalls.push(data),
|
|
15
|
+
* );
|
|
16
|
+
* // Use `wrapped` as the MCP client's sampling handler
|
|
17
|
+
* // After tool execution, `samplingCalls` contains metrics for all nested LLM calls
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function wrapSamplingHandler(handler, onSamplingCall) {
|
|
21
|
+
return async (request) => {
|
|
22
|
+
const startTime = Date.now();
|
|
23
|
+
const response = await handler(request);
|
|
24
|
+
const durationMs = Date.now() - startTime;
|
|
25
|
+
const modelId = response.model ?? request.params.modelPreferences?.hints?.[0]?.name;
|
|
26
|
+
const inputTokens = response.usage?.inputTokens ?? response.usage?.promptTokens;
|
|
27
|
+
const outputTokens = response.usage?.outputTokens ?? response.usage?.completionTokens;
|
|
28
|
+
const reasoningTokens = response.usage?.reasoningTokens;
|
|
29
|
+
const cachedInputTokens = response.usage?.cachedInputTokens;
|
|
30
|
+
onSamplingCall({
|
|
31
|
+
...modelId ? { model_id: modelId } : void 0,
|
|
32
|
+
...inputTokens != null ? { input_tokens: inputTokens } : void 0,
|
|
33
|
+
...outputTokens != null ? { output_tokens: outputTokens } : void 0,
|
|
34
|
+
...reasoningTokens != null ? { reasoning_tokens: reasoningTokens } : void 0,
|
|
35
|
+
...cachedInputTokens != null ? { cached_input_tokens: cachedInputTokens } : void 0,
|
|
36
|
+
duration_ms: durationMs
|
|
37
|
+
});
|
|
38
|
+
return response;
|
|
39
|
+
};
|
|
50
40
|
}
|
|
51
41
|
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
42
|
+
* Creates a collector that accumulates sampling call data during tool execution.
|
|
43
|
+
* Use with `wrapSamplingHandler` to capture all sampling calls for a tool invocation.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* const collector = createSamplingCollector();
|
|
48
|
+
* const wrappedHandler = wrapSamplingHandler(handler, collector.collect);
|
|
49
|
+
* // ... execute MCP tool ...
|
|
50
|
+
* const calls = collector.getCalls(); // SamplingCallData[]
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
function createSamplingCollector() {
|
|
54
|
+
const calls = [];
|
|
55
|
+
return {
|
|
56
|
+
collect: (data) => calls.push(data),
|
|
57
|
+
getCalls: () => [...calls],
|
|
58
|
+
reset: () => {
|
|
59
|
+
calls.length = 0;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
72
62
|
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { createSamplingCollector, wrapSamplingHandler };
|
|
65
|
+
|
|
73
66
|
//# sourceMappingURL=instrumentMcpSampling.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrumentMcpSampling.js","
|
|
1
|
+
{"version":3,"file":"instrumentMcpSampling.js","names":[],"sources":["../src/instrumentMcpSampling.ts"],"sourcesContent":["/**\n * MCP sampling instrumentation utility.\n *\n * Wraps an MCP client's sampling handler to capture nested LLM calls\n * (sampling/createMessage requests) made during tool execution.\n * The captured data can be reported as child generation spans.\n */\n\nexport type SamplingCallData = {\n model_id?: string;\n input_tokens?: number;\n output_tokens?: number;\n reasoning_tokens?: number;\n cached_input_tokens?: number;\n duration_ms?: number;\n};\n\nexport type McpSamplingHandler = (\n request: McpSamplingRequest,\n) => Promise<McpSamplingResponse>;\n\nexport type McpSamplingRequest = {\n method: \"sampling/createMessage\";\n params: {\n messages: unknown[];\n modelPreferences?: { hints?: { name?: string }[] };\n maxTokens?: number;\n [key: string]: unknown;\n };\n};\n\nexport type McpSamplingResponse = {\n model?: string;\n content: unknown;\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n promptTokens?: number;\n completionTokens?: number;\n reasoningTokens?: number;\n cachedInputTokens?: number;\n };\n [key: string]: unknown;\n};\n\n/**\n * Wraps an MCP sampling handler to intercept and measure sampling calls.\n *\n * @param handler - The original sampling handler from the MCP client\n * @param onSamplingCall - Callback invoked with metrics for each sampling call\n * @returns A wrapped handler that transparently captures sampling metrics\n *\n * @example\n * ```ts\n * const samplingCalls: SamplingCallData[] = [];\n * const wrapped = wrapSamplingHandler(\n * originalHandler,\n * (data) => samplingCalls.push(data),\n * );\n * // Use `wrapped` as the MCP client's sampling handler\n * // After tool execution, `samplingCalls` contains metrics for all nested LLM calls\n * ```\n */\nexport function wrapSamplingHandler(\n handler: McpSamplingHandler,\n onSamplingCall: (data: SamplingCallData) => void,\n): McpSamplingHandler {\n return async (request) => {\n const startTime = Date.now();\n const response = await handler(request);\n const durationMs = Date.now() - startTime;\n\n const modelId =\n response.model ?? request.params.modelPreferences?.hints?.[0]?.name;\n\n const inputTokens =\n response.usage?.inputTokens ?? response.usage?.promptTokens;\n const outputTokens =\n response.usage?.outputTokens ?? response.usage?.completionTokens;\n const reasoningTokens = response.usage?.reasoningTokens;\n const cachedInputTokens = response.usage?.cachedInputTokens;\n\n onSamplingCall({\n ...(modelId ? { model_id: modelId } : undefined),\n ...(inputTokens != null ? { input_tokens: inputTokens } : undefined),\n ...(outputTokens != null ? { output_tokens: outputTokens } : undefined),\n ...(reasoningTokens != null\n ? { reasoning_tokens: reasoningTokens }\n : undefined),\n ...(cachedInputTokens != null\n ? { cached_input_tokens: cachedInputTokens }\n : undefined),\n duration_ms: durationMs,\n });\n\n return response;\n };\n}\n\n/**\n * Creates a collector that accumulates sampling call data during tool execution.\n * Use with `wrapSamplingHandler` to capture all sampling calls for a tool invocation.\n *\n * @example\n * ```ts\n * const collector = createSamplingCollector();\n * const wrappedHandler = wrapSamplingHandler(handler, collector.collect);\n * // ... execute MCP tool ...\n * const calls = collector.getCalls(); // SamplingCallData[]\n * ```\n */\nexport function createSamplingCollector() {\n const calls: SamplingCallData[] = [];\n return {\n collect: (data: SamplingCallData) => calls.push(data),\n getCalls: () => [...calls],\n reset: () => {\n calls.length = 0;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA+DA,SAAgB,oBACd,SACA,gBACoB;CACpB,OAAO,OAAO,YAAY;EACxB,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,WAAW,MAAM,QAAQ,OAAO;EACtC,MAAM,aAAa,KAAK,IAAI,IAAI;EAEhC,MAAM,UACJ,SAAS,SAAS,QAAQ,OAAO,kBAAkB,QAAQ,IAAI;EAEjE,MAAM,cACJ,SAAS,OAAO,eAAe,SAAS,OAAO;EACjD,MAAM,eACJ,SAAS,OAAO,gBAAgB,SAAS,OAAO;EAClD,MAAM,kBAAkB,SAAS,OAAO;EACxC,MAAM,oBAAoB,SAAS,OAAO;EAE1C,eAAe;GACb,GAAI,UAAU,EAAE,UAAU,QAAQ,IAAI,KAAA;GACtC,GAAI,eAAe,OAAO,EAAE,cAAc,YAAY,IAAI,KAAA;GAC1D,GAAI,gBAAgB,OAAO,EAAE,eAAe,aAAa,IAAI,KAAA;GAC7D,GAAI,mBAAmB,OACnB,EAAE,kBAAkB,gBAAgB,IACpC,KAAA;GACJ,GAAI,qBAAqB,OACrB,EAAE,qBAAqB,kBAAkB,IACzC,KAAA;GACJ,aAAa;EACf,CAAC;EAED,OAAO;CACT;AACF;;;;;;;;;;;;;AAcA,SAAgB,0BAA0B;CACxC,MAAM,QAA4B,CAAC;CACnC,OAAO;EACL,UAAU,SAA2B,MAAM,KAAK,IAAI;EACpD,gBAAgB,CAAC,GAAG,KAAK;EACzB,aAAa;GACX,MAAM,SAAS;EACjB;CACF;AACF"}
|
package/dist/tests/setup.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export {};
|
|
2
|
-
//# sourceMappingURL=setup.d.ts.map
|
|
1
|
+
export { };
|
package/dist/tests/setup.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
// This file contains setup code for tests
|
|
2
1
|
import { vi } from "vitest";
|
|
3
|
-
|
|
4
|
-
// Using a fixed date to avoid recursive calls
|
|
2
|
+
//#region src/tests/setup.ts
|
|
5
3
|
const OriginalDate = globalThis.Date;
|
|
6
4
|
const fixedDate = new OriginalDate("2023-01-01");
|
|
7
5
|
globalThis.Date = vi.fn(() => fixedDate);
|
|
8
6
|
globalThis.Date.now = vi.fn(() => fixedDate.getTime());
|
|
9
|
-
|
|
7
|
+
//#endregion
|
|
8
|
+
|
|
10
9
|
//# sourceMappingURL=setup.js.map
|
package/dist/tests/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","
|
|
1
|
+
{"version":3,"file":"setup.js","names":[],"sources":["../../src/tests/setup.ts"],"sourcesContent":["// This file contains setup code for tests\nimport { vi } from \"vitest\";\n\n// Set up globalThis mocks if needed\n// Using a fixed date to avoid recursive calls\nconst OriginalDate = globalThis.Date;\nconst fixedDate = new OriginalDate(\"2023-01-01\");\nglobalThis.Date = vi.fn(() => fixedDate) as any;\nglobalThis.Date.now = vi.fn(() => fixedDate.getTime());\n\n// Add any other globalThis setup needed for tests\n"],"mappings":";;AAKA,MAAM,eAAe,WAAW;AAChC,MAAM,YAAY,IAAI,aAAa,YAAY;AAC/C,WAAW,OAAO,GAAG,SAAS,SAAS;AACvC,WAAW,KAAK,MAAM,GAAG,SAAS,UAAU,QAAQ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assistant-cloud",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"description": "Cloud integration for assistant-ui",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"assistant",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
],
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"assistant-stream": "^0.3.
|
|
30
|
+
"assistant-stream": "^0.3.16"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@types/node": "^25.
|
|
34
|
-
"vitest": "^4.1.
|
|
35
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
33
|
+
"@types/node": "^25.9.1",
|
|
34
|
+
"vitest": "^4.1.7",
|
|
35
|
+
"@assistant-ui/x-buildutils": "0.0.9"
|
|
36
36
|
},
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public",
|
package/src/AssistantCloudAPI.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type AssistantCloudConfig = (
|
|
|
24
24
|
authToken: () => Promise<string | null>;
|
|
25
25
|
}
|
|
26
26
|
| {
|
|
27
|
+
baseUrl?: string;
|
|
27
28
|
apiKey: string;
|
|
28
29
|
userId: string;
|
|
29
30
|
workspaceId: string;
|
|
@@ -70,7 +71,9 @@ export class AssistantCloudAPI {
|
|
|
70
71
|
this._baseUrl = config.baseUrl;
|
|
71
72
|
this._auth = new AssistantCloudJWTAuthStrategy(config.authToken);
|
|
72
73
|
} else if ("apiKey" in config) {
|
|
73
|
-
this._baseUrl =
|
|
74
|
+
this._baseUrl = (
|
|
75
|
+
config.baseUrl ?? "https://backend.assistant-api.com"
|
|
76
|
+
).replace(/\/$/, "");
|
|
74
77
|
this._auth = new AssistantCloudAPIKeyAuthStrategy(
|
|
75
78
|
config.apiKey,
|
|
76
79
|
config.userId,
|
|
@@ -48,6 +48,48 @@ describe("AssistantCloudAPI", () => {
|
|
|
48
48
|
expect(init.body).toBe(JSON.stringify({ hello: "world" }));
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
it("uses custom baseUrl when provided with apiKey config", async () => {
|
|
52
|
+
const fetchMock = vi.fn().mockResolvedValue({
|
|
53
|
+
ok: true,
|
|
54
|
+
headers: new Headers(),
|
|
55
|
+
json: vi.fn().mockResolvedValue({}),
|
|
56
|
+
});
|
|
57
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
58
|
+
|
|
59
|
+
const api = new AssistantCloudAPI({
|
|
60
|
+
baseUrl: "https://custom.example.com",
|
|
61
|
+
apiKey: "test-key",
|
|
62
|
+
userId: "u-1",
|
|
63
|
+
workspaceId: "w-1",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await api.makeRawRequest("/threads");
|
|
67
|
+
|
|
68
|
+
const [url] = fetchMock.mock.calls[0]!;
|
|
69
|
+
expect(url.toString()).toBe("https://custom.example.com/v1/threads");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("strips a trailing slash from a custom baseUrl", async () => {
|
|
73
|
+
const fetchMock = vi.fn().mockResolvedValue({
|
|
74
|
+
ok: true,
|
|
75
|
+
headers: new Headers(),
|
|
76
|
+
json: vi.fn().mockResolvedValue({}),
|
|
77
|
+
});
|
|
78
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
79
|
+
|
|
80
|
+
const api = new AssistantCloudAPI({
|
|
81
|
+
baseUrl: "https://custom.example.com/",
|
|
82
|
+
apiKey: "test-key",
|
|
83
|
+
userId: "u-1",
|
|
84
|
+
workspaceId: "w-1",
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await api.makeRawRequest("/threads");
|
|
88
|
+
|
|
89
|
+
const [url] = fetchMock.mock.calls[0]!;
|
|
90
|
+
expect(url.toString()).toBe("https://custom.example.com/v1/threads");
|
|
91
|
+
});
|
|
92
|
+
|
|
51
93
|
it("rejects before fetch when auth token callback returns null", async () => {
|
|
52
94
|
const fetchMock = vi.fn();
|
|
53
95
|
vi.stubGlobal("fetch", fetchMock);
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,0CAAuC;AACnE,YAAY,EAAE,6BAA6B,EAAE,+BAA4B;AACzE,YAAY,EAAE,uBAAuB,EAAE,gCAA6B;AACpE,OAAO,EAAE,cAAc,EAAE,4BAAyB;AAClD,OAAO,EAAE,uBAAuB,EAAE,qCAAkC;AACpE,OAAO,EACL,0BAA0B,EAC1B,KAAK,oBAAoB,GAC1B,uCAAoC;AACrC,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,GACxB,mCAAgC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,4BAAyB;AAClD,OAAO,EAAE,uBAAuB,EAAE,qCAAkC;AACpE,OAAO,EACL,0BAA0B,GAE3B,uCAAoC;AACrC,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GAGxB,mCAAgC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/tests/setup.ts"],"names":[],"mappings":""}
|