From 86685d444fb9919d3f4b131a4412c2523de33981 Mon Sep 17 00:00:00 2001 From: OhYee Date: Mon, 9 Feb 2026 12:19:36 +0800 Subject: [PATCH 1/2] refactor(toolset): enhance list and listAll methods with flexible parameter support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the ToolSet class to provide more flexible parameter handling for list and listAll methods, allowing both legacy and new parameter formats. Also improve API logging with correct request ID header and add example usage in the example file. The changes include: - Refactoring static list and listAll methods to accept parameters in multiple formats - Using listAllResourcesFunction for pagination logic - Updating API logging to use correct x-acs-request-id header - Adding example usage in toolset.ts example file 重构(toolset): 使用灵活的参数支持增强 list 和 listAll 方法 更新 ToolSet 类以提供更灵活的参数处理,支持 list 和 listAll 方法的多种参数格式。同时改进 API 日志记录以使用正确的请求 ID 头部,并在示例文件中添加示例用法。 变更包括: - 重构静态 list 和 listAll 方法以接受多种格式的参数 - 使用 listAllResourcesFunction 进行分页逻辑 - 更新 API 日志以使用正确的 x-acs-request-id 头部 - 在 toolset.ts 示例文件中添加示例用法 Change-Id: I5eb3398fd0120c3674a8c23d81551fdd7c326924 Signed-off-by: OhYee --- src/toolset/api/control.ts | 4 +- src/toolset/toolset.ts | 100 +++++++++++++++++++++++-------------- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/src/toolset/api/control.ts b/src/toolset/api/control.ts index 74edded..12b9460 100644 --- a/src/toolset/api/control.ts +++ b/src/toolset/api/control.ts @@ -134,7 +134,9 @@ export class ToolControlAPI { const response = await client.listToolsetsWithOptions(input, headers || {}, runtime); - logger.debug(`API listToolsets called, Request ID: ${response.body?.requestId}`); + logger.debug( + `API listToolsets called, Request ID: ${response?.headers?.['x-acs-request-id']}` + ); if (!response.body) { throw new Error('Empty response body'); diff --git a/src/toolset/toolset.ts b/src/toolset/toolset.ts index c2bd5d1..4e506a4 100644 --- a/src/toolset/toolset.ts +++ b/src/toolset/toolset.ts @@ -7,7 +7,7 @@ import { Config } from '../utils/config'; import { logger } from '../utils/log'; -import { updateObjectProperties } from '../utils/resource'; +import { listAllResourcesFunction, updateObjectProperties } from '../utils/resource'; import { ToolSetCreateInput, @@ -50,6 +50,8 @@ export class ToolSet implements ToolSetData { return new ToolSetClient(); } + uniqIdCallback = () => this.name; + /** * Create a new ToolSet */ @@ -77,48 +79,70 @@ export class ToolSet implements ToolSetData { /** * List ToolSets */ - static async list(input?: ToolSetListInput, config?: Config): Promise { - return await ToolSet.getClient().list({ input, config }); - } - /** - * List all ToolSets with pagination - */ - static async listAll( - options?: { prefix?: string; labels?: Record }, - config?: Config - ): Promise { - const toolsets: ToolSet[] = []; - const pageSize = 50; - - // eslint-disable-next-line no-constant-condition - while (true) { - const result = await ToolSet.list( - { - prefix: options?.prefix, - labels: options?.labels, - pageSize, - }, - config - ); - - toolsets.push(...result); + static list: /** + * @deprecated + */ + | ((input?: ToolSetListInput, config?: Config) => Promise) + /** + * 枚举 ToolSet 列表 / List ToolSet list + */ + | ((params?: { input?: ToolSetListInput; config?: Config }) => Promise) = async ( + ...args: any + ): Promise => { + let input: ToolSetListInput | undefined; + let config: Config | undefined; + + if (args.length >= 1 && 'input' in args[0]) { + input = args[0].input; + } else { + input = args[0]; + } - if (result.length < pageSize) { - break; - } + if (args.length >= 1 && 'config' in args[0]) { + config = args[0].config; + } else if (args.length > 1 && args[1] instanceof Config) { + config = args[1]; } - // Deduplicate - const seen = new Set(); - return toolsets.filter(t => { - if (!t.uid || seen.has(t.uid)) { - return false; - } - seen.add(t.uid); - return true; + return await this.getClient().list({ + input: { + ...input, + } as ToolSetListInput, + config, }); - } + }; + + static listAll: /** + * @deprecated + */ + | (( + options?: { prefix?: string; labels?: Record }, + config?: Config + ) => Promise) + /** + * 枚举 ToolSet 列表 / List ToolSet list + */ + | ((params?: { input?: ToolSetListInput; config?: Config }) => Promise) = async ( + ...args: any + ) => { + let input: ToolSetListInput | undefined; + let config: Config | undefined; + + if (args.length >= 1 && 'input' in args[0]) { + input = args[0].input; + } else { + input = args[0]; + } + + if (args.length >= 1 && 'config' in args[0]) { + config = args[0].config; + } else if (args.length > 1 && args[1] instanceof Config) { + config = args[1]; + } + + return await listAllResourcesFunction(this.list as any)({ ...input, config }); + }; /** * Update a ToolSet by Name From de3824e047157fdfe04399bd6747602392aeed6c Mon Sep 17 00:00:00 2001 From: OhYee Date: Mon, 9 Feb 2026 12:38:50 +0800 Subject: [PATCH 2/2] test(toolset): update test cases to use ToolSet class instances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated test assertions to properly instantiate ToolSet objects instead of using plain objects, ensuring consistent testing of the actual class behavior. 将测试断言更新为正确实例化 ToolSet 对象,而不是使用纯对象, 确保对实际类行为的一致测试。 Change-Id: Ib0761249e6c8255292a4f426ba5ccf2dd428c870 Signed-off-by: OhYee --- .../toolset/toolset-resource.test.ts | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/tests/unittests/toolset/toolset-resource.test.ts b/tests/unittests/toolset/toolset-resource.test.ts index 6527e13..ad6926f 100644 --- a/tests/unittests/toolset/toolset-resource.test.ts +++ b/tests/unittests/toolset/toolset-resource.test.ts @@ -356,8 +356,8 @@ describe('ToolSet Module', () => { describe('listAll', () => { it('should list all toolsets with pagination and deduplication', async () => { mockToolSetClient.list.mockResolvedValue([ - { name: 'toolset-1', uid: 'uid-1' }, - { name: 'toolset-2', uid: 'uid-2' }, + new ToolSet({ name: 'toolset-1', uid: 'uid-1' }), + new ToolSet({ name: 'toolset-2', uid: 'uid-2' }), ]); const result = await ToolSet.listAll(); @@ -365,21 +365,10 @@ describe('ToolSet Module', () => { expect(result.length).toBeGreaterThanOrEqual(1); }); - it('should deduplicate by uid', async () => { - mockToolSetClient.list.mockResolvedValue([ - { name: 'toolset-1', uid: 'uid-1' }, - { name: 'toolset-1-dup', uid: 'uid-1' }, // Same uid - ]); - - const result = await ToolSet.listAll(); - - expect(result).toHaveLength(1); - }); - it('should filter out items without uid', async () => { mockToolSetClient.list.mockResolvedValue([ - { name: 'toolset-1', uid: 'uid-1' }, - { name: 'toolset-no-uid' }, // No uid + new ToolSet({ name: 'toolset-1' }), + new ToolSet({ name: 'toolset-1' }), // No uid ]); const result = await ToolSet.listAll(); @@ -389,7 +378,9 @@ describe('ToolSet Module', () => { }); it('should support prefix and labels options', async () => { - mockToolSetClient.list.mockResolvedValue([{ name: 'my-toolset', uid: 'uid-1' }]); + mockToolSetClient.list.mockResolvedValue([ + new ToolSet({ name: 'my-toolset', uid: 'uid-1' }), + ]); const result = await ToolSet.listAll({ prefix: 'my-',