@coze-arch/cli 0.0.14 → 0.0.15-alpha.a0f5b9

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.
Files changed (91) hide show
  1. package/lib/__templates__/nextjs/scripts/prepare.sh +3 -0
  2. package/lib/__templates__/nuxt-vue/scripts/prepare.sh +3 -0
  3. package/lib/__templates__/pi-agent/.coze +10 -0
  4. package/lib/__templates__/pi-agent/AGENTS.md +140 -0
  5. package/lib/__templates__/pi-agent/README.md +172 -0
  6. package/lib/__templates__/pi-agent/_gitignore +3 -0
  7. package/lib/__templates__/pi-agent/_npmrc +23 -0
  8. package/lib/__templates__/pi-agent/docs/project-overview.md +356 -0
  9. package/lib/__templates__/pi-agent/docs/user/getting-started.md +47 -0
  10. package/lib/__templates__/pi-agent/package.json +60 -0
  11. package/lib/__templates__/pi-agent/pi-resources/SYSTEM.md +15 -0
  12. package/lib/__templates__/pi-agent/pi-resources/extensions/preference-memory/index.ts +355 -0
  13. package/lib/__templates__/pi-agent/pi-resources/extensions/test-ping.ts +19 -0
  14. package/lib/__templates__/pi-agent/pi-resources/prompts/test-prompt.md +11 -0
  15. package/lib/__templates__/pi-agent/pi-resources/skills/coze-asr/SKILL.md +36 -0
  16. package/lib/__templates__/pi-agent/pi-resources/skills/coze-asr/scripts/asr.mjs +9 -0
  17. package/lib/__templates__/pi-agent/pi-resources/skills/coze-image-gen/SKILL.md +41 -0
  18. package/lib/__templates__/pi-agent/pi-resources/skills/coze-image-gen/scripts/gen.mjs +9 -0
  19. package/lib/__templates__/pi-agent/pi-resources/skills/coze-tts/SKILL.md +85 -0
  20. package/lib/__templates__/pi-agent/pi-resources/skills/coze-tts/scripts/tts.mjs +9 -0
  21. package/lib/__templates__/pi-agent/pi-resources/skills/coze-video-gen/SKILL.md +53 -0
  22. package/lib/__templates__/pi-agent/pi-resources/skills/coze-video-gen/scripts/gen.mjs +9 -0
  23. package/lib/__templates__/pi-agent/pnpm-lock.yaml +8285 -0
  24. package/lib/__templates__/pi-agent/scripts/dev.sh +14 -0
  25. package/lib/__templates__/pi-agent/scripts/prepare.sh +2 -0
  26. package/lib/__templates__/pi-agent/src/agent.ts +363 -0
  27. package/lib/__templates__/pi-agent/src/channels/feishu/index.ts +760 -0
  28. package/lib/__templates__/pi-agent/src/channels/feishu/streaming-card.ts +297 -0
  29. package/lib/__templates__/pi-agent/src/channels/wechat/index.ts +171 -0
  30. package/lib/__templates__/pi-agent/src/config.ts +596 -0
  31. package/lib/__templates__/pi-agent/src/core.ts +218 -0
  32. package/lib/__templates__/pi-agent/src/dashboard/api/channels.ts +148 -0
  33. package/lib/__templates__/pi-agent/src/dashboard/api/docs.ts +204 -0
  34. package/lib/__templates__/pi-agent/src/dashboard/api/models.ts +141 -0
  35. package/lib/__templates__/pi-agent/src/dashboard/api/overview.ts +33 -0
  36. package/lib/__templates__/pi-agent/src/dashboard/config-store.ts +64 -0
  37. package/lib/__templates__/pi-agent/src/dashboard/index.ts +39 -0
  38. package/lib/__templates__/pi-agent/src/dashboard/server.ts +622 -0
  39. package/lib/__templates__/pi-agent/src/dashboard/types.ts +25 -0
  40. package/lib/__templates__/pi-agent/src/dashboard/web/index.html +13 -0
  41. package/lib/__templates__/pi-agent/src/dashboard/web/postcss.config.cjs +7 -0
  42. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/app-layout.tsx +186 -0
  43. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/page-title.tsx +17 -0
  44. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/alert.tsx +22 -0
  45. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/badge.tsx +25 -0
  46. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/button.tsx +40 -0
  47. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/card.tsx +29 -0
  48. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/input.tsx +18 -0
  49. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/label.tsx +8 -0
  50. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/select.tsx +80 -0
  51. package/lib/__templates__/pi-agent/src/dashboard/web/src/components/ui/separator.tsx +23 -0
  52. package/lib/__templates__/pi-agent/src/dashboard/web/src/hooks/use-fetch.ts +32 -0
  53. package/lib/__templates__/pi-agent/src/dashboard/web/src/hooks/use-local-storage-state.ts +23 -0
  54. package/lib/__templates__/pi-agent/src/dashboard/web/src/main.tsx +30 -0
  55. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/channels-page.tsx +188 -0
  56. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/chat-page.tsx +451 -0
  57. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/docs-page.tsx +65 -0
  58. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/models-page.tsx +122 -0
  59. package/lib/__templates__/pi-agent/src/dashboard/web/src/pages/overview-page.tsx +134 -0
  60. package/lib/__templates__/pi-agent/src/dashboard/web/src/services/chat-ws-service.ts +167 -0
  61. package/lib/__templates__/pi-agent/src/dashboard/web/src/styles.css +294 -0
  62. package/lib/__templates__/pi-agent/src/dashboard/web/src/utils/index.ts +11 -0
  63. package/lib/__templates__/pi-agent/src/dashboard/web/tsconfig.json +13 -0
  64. package/lib/__templates__/pi-agent/src/dashboard/web/vite.config.ts +17 -0
  65. package/lib/__templates__/pi-agent/src/index.ts +123 -0
  66. package/lib/__templates__/pi-agent/src/pi-resources.ts +125 -0
  67. package/lib/__templates__/pi-agent/src/session-store.ts +223 -0
  68. package/lib/__templates__/pi-agent/src/tools/common/format-coze-error.ts +12 -0
  69. package/lib/__templates__/pi-agent/src/tools/index.ts +2 -0
  70. package/lib/__templates__/pi-agent/src/tools/web-fetch/index.ts +195 -0
  71. package/lib/__templates__/pi-agent/src/tools/web-search/index.ts +206 -0
  72. package/lib/__templates__/pi-agent/template.config.js +45 -0
  73. package/lib/__templates__/pi-agent/tests/config.test.ts +315 -0
  74. package/lib/__templates__/pi-agent/tests/dashboard-docs-api.test.ts +125 -0
  75. package/lib/__templates__/pi-agent/tests/dashboard-models-api.test.ts +171 -0
  76. package/lib/__templates__/pi-agent/tests/feishu-channel.test.ts +149 -0
  77. package/lib/__templates__/pi-agent/tests/feishu-streaming-card.test.ts +15 -0
  78. package/lib/__templates__/pi-agent/tests/pi-resources.test.ts +73 -0
  79. package/lib/__templates__/pi-agent/tests/preference-memory.test.ts +43 -0
  80. package/lib/__templates__/pi-agent/tests/session-store.test.ts +61 -0
  81. package/lib/__templates__/pi-agent/tests/smoke/run-smoke.ts +275 -0
  82. package/lib/__templates__/pi-agent/tests/web-fetch.test.ts +157 -0
  83. package/lib/__templates__/pi-agent/tests/web-search.test.ts +208 -0
  84. package/lib/__templates__/pi-agent/tsconfig.json +21 -0
  85. package/lib/__templates__/pi-agent/types/larksuiteoapi-node-sdk.d.ts +113 -0
  86. package/lib/__templates__/taro/pnpm-lock.yaml +24 -14
  87. package/lib/__templates__/taro/server/package.json +0 -2
  88. package/lib/__templates__/templates.json +24 -0
  89. package/lib/__templates__/vite/scripts/prepare.sh +3 -0
  90. package/lib/cli.js +106 -8
  91. package/package.json +1 -1
@@ -0,0 +1,157 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { FetchClient, type FetchResponse } from "coze-coding-dev-sdk";
4
+ import { cozeWebFetchTool } from "../src/tools/web-fetch/index.js";
5
+
6
+ function resultText(result: { content: { type: string; text?: string }[] }): string {
7
+ return result.content[0].text ?? "";
8
+ }
9
+
10
+ function makeFetchResponse(overrides: Partial<FetchResponse> = {}): FetchResponse {
11
+ return {
12
+ url: "https://example.com",
13
+ title: "Example Page",
14
+ content: [
15
+ { type: "text", text: "Hello world" },
16
+ { type: "link", text: "Link A", url: "https://a.com" },
17
+ { type: "image", image: { display_url: "https://img.com/1.png", width: 640, height: 480 } },
18
+ ],
19
+ ...overrides,
20
+ };
21
+ }
22
+
23
+ test("web-fetch: text format renders numbered items with links and images", async (t) => {
24
+ const resp = makeFetchResponse();
25
+ t.mock.method(FetchClient.prototype, "fetch", async () => resp);
26
+
27
+ const result = await cozeWebFetchTool.execute("call-1", { urls: "https://example.com" }, undefined as any, undefined as any, undefined as any);
28
+ const text = resultText(result);
29
+
30
+ assert.ok(text.includes("1. Example Page"));
31
+ assert.ok(text.includes("URL: https://example.com"));
32
+ assert.ok(text.includes("Hello world"));
33
+ assert.ok(text.includes("Link A: https://a.com"));
34
+ assert.ok(text.includes("https://img.com/1.png (640x480)"));
35
+ });
36
+
37
+ test("web-fetch: markdown format renders headings and markdown links", async (t) => {
38
+ const resp = makeFetchResponse();
39
+ t.mock.method(FetchClient.prototype, "fetch", async () => resp);
40
+
41
+ const result = await cozeWebFetchTool.execute("call-2", { urls: ["https://example.com"], format: "markdown" }, undefined as any, undefined as any, undefined as any);
42
+ const text = resultText(result);
43
+
44
+ assert.ok(text.includes("# Example Page"));
45
+ assert.ok(text.includes("- [Link A](https://a.com)"));
46
+ });
47
+
48
+ test("web-fetch: json format returns valid JSON", async (t) => {
49
+ const resp = makeFetchResponse();
50
+ t.mock.method(FetchClient.prototype, "fetch", async () => resp);
51
+
52
+ const result = await cozeWebFetchTool.execute("call-3", { urls: "https://example.com", format: "json" }, undefined as any, undefined as any, undefined as any);
53
+ const parsed = JSON.parse(resultText(result));
54
+
55
+ assert.equal(Array.isArray(parsed), true);
56
+ assert.equal(parsed[0].url, "https://example.com");
57
+ assert.equal(parsed[0].title, "Example Page");
58
+ assert.equal(parsed[0].links.length, 1);
59
+ assert.equal(parsed[0].images.length, 1);
60
+ });
61
+
62
+ test("web-fetch: textOnly omits links and images", async (t) => {
63
+ const resp = makeFetchResponse();
64
+ t.mock.method(FetchClient.prototype, "fetch", async () => resp);
65
+
66
+ const result = await cozeWebFetchTool.execute("call-4", { urls: "https://example.com", format: "json", textOnly: true }, undefined as any, undefined as any, undefined as any);
67
+ const parsed = JSON.parse(resultText(result));
68
+
69
+ assert.equal(parsed[0].links.length, 0);
70
+ assert.equal(parsed[0].images.length, 0);
71
+ });
72
+
73
+ test("web-fetch: filters out links with missing url", async (t) => {
74
+ const resp = makeFetchResponse({
75
+ content: [
76
+ { type: "text", text: "body" },
77
+ { type: "link", text: "Valid", url: "https://valid.com" },
78
+ { type: "link", text: "Missing URL" },
79
+ { type: "link", text: undefined, url: undefined },
80
+ ],
81
+ });
82
+ t.mock.method(FetchClient.prototype, "fetch", async () => resp);
83
+
84
+ const textResult = await cozeWebFetchTool.execute("call-5a", { urls: "https://example.com" }, undefined as any, undefined as any, undefined as any);
85
+ assert.ok(resultText(textResult).includes("Valid: https://valid.com"));
86
+ assert.ok(!resultText(textResult).includes("Missing URL"));
87
+
88
+ const mdResult = await cozeWebFetchTool.execute("call-5b", { urls: "https://example.com", format: "markdown" }, undefined as any, undefined as any, undefined as any);
89
+ assert.ok(resultText(mdResult).includes("[Valid](https://valid.com)"));
90
+ assert.ok(!resultText(mdResult).includes("Missing URL"));
91
+ });
92
+
93
+ test("web-fetch: image dimensions only shown when both width and height are numbers", async (t) => {
94
+ const resp = makeFetchResponse({
95
+ content: [
96
+ { type: "text", text: "body" },
97
+ { type: "image", image: { display_url: "https://img.com/a.png", width: 100, height: 200 } },
98
+ { type: "image", image: { display_url: "https://img.com/b.png", width: 100 } },
99
+ { type: "image", image: { display_url: "https://img.com/c.png" } },
100
+ ],
101
+ });
102
+ t.mock.method(FetchClient.prototype, "fetch", async () => resp);
103
+
104
+ const result = await cozeWebFetchTool.execute("call-6", { urls: "https://example.com" }, undefined as any, undefined as any, undefined as any);
105
+ const text = resultText(result);
106
+
107
+ assert.ok(text.includes("https://img.com/a.png (100x200)"));
108
+ assert.ok(text.includes("https://img.com/b.png"));
109
+ assert.ok(!text.includes("b.png (100x"));
110
+ assert.ok(text.includes("https://img.com/c.png"));
111
+ assert.ok(!text.includes("c.png ("));
112
+ });
113
+
114
+ test("web-fetch: concurrent fetching preserves order", async (t) => {
115
+ const callOrder: number[] = [];
116
+ let callIndex = 0;
117
+
118
+ t.mock.method(FetchClient.prototype, "fetch", async (url: string) => {
119
+ const idx = callIndex++;
120
+ const delay = url.includes("slow") ? 50 : 10;
121
+ await new Promise((r) => setTimeout(r, delay));
122
+ callOrder.push(idx);
123
+ return makeFetchResponse({ url, title: `Page ${idx}` });
124
+ });
125
+
126
+ const urls = ["https://slow.com", "https://fast1.com", "https://fast2.com"];
127
+ const result = await cozeWebFetchTool.execute("call-7", { urls, format: "json" }, undefined as any, undefined as any, undefined as any);
128
+ const parsed = JSON.parse(resultText(result));
129
+
130
+ assert.equal(parsed.length, 3);
131
+ assert.equal(parsed[0].url, "https://slow.com");
132
+ assert.equal(parsed[1].url, "https://fast1.com");
133
+ assert.equal(parsed[2].url, "https://fast2.com");
134
+ });
135
+
136
+ test("web-fetch: returns error content on fetch failure", async (t) => {
137
+ t.mock.method(FetchClient.prototype, "fetch", async () => {
138
+ throw new Error("Connection refused");
139
+ });
140
+
141
+ const result = await cozeWebFetchTool.execute("call-8", { urls: "https://example.com" }, undefined as any, undefined as any, undefined as any);
142
+
143
+ assert.ok(resultText(result).includes("Error: Connection refused"));
144
+ assert.equal((result as any).details.error, true);
145
+ });
146
+
147
+ test("web-fetch: single url string is normalized to array", async (t) => {
148
+ const calls: string[] = [];
149
+ t.mock.method(FetchClient.prototype, "fetch", async (url: string) => {
150
+ calls.push(url);
151
+ return makeFetchResponse({ url });
152
+ });
153
+
154
+ await cozeWebFetchTool.execute("call-9", { urls: "https://single.com" }, undefined as any, undefined as any, undefined as any);
155
+
156
+ assert.deepEqual(calls, ["https://single.com"]);
157
+ });
@@ -0,0 +1,208 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+ import { SearchClient, type SearchResponse } from "coze-coding-dev-sdk";
4
+ import { cozeWebSearchTool } from "../src/tools/web-search/index.js";
5
+
6
+ function resultText(result: { content: { type: string; text?: string }[] }): string {
7
+ return result.content[0].text ?? "";
8
+ }
9
+
10
+ function makeWebSearchResponse(overrides: Partial<SearchResponse> = {}): SearchResponse {
11
+ return {
12
+ web_items: [
13
+ {
14
+ id: "1",
15
+ sort_id: 1,
16
+ title: "Result A",
17
+ site_name: "example.com",
18
+ url: "https://example.com/a",
19
+ snippet: "Snippet A",
20
+ auth_info_des: "",
21
+ auth_info_level: 0,
22
+ },
23
+ {
24
+ id: "2",
25
+ sort_id: 2,
26
+ title: "Result B",
27
+ url: "https://example.com/b",
28
+ snippet: "Snippet B",
29
+ publish_time: "2025-01-01",
30
+ auth_info_des: "",
31
+ auth_info_level: 0,
32
+ },
33
+ ],
34
+ image_items: [],
35
+ ...overrides,
36
+ };
37
+ }
38
+
39
+ function makeImageSearchResponse(): SearchResponse {
40
+ return {
41
+ web_items: [],
42
+ image_items: [
43
+ {
44
+ id: "img-1",
45
+ sort_id: 1,
46
+ title: "Cat Photo",
47
+ url: "https://example.com/cat",
48
+ site_name: "photos.com",
49
+ image: { url: "https://cdn.com/cat.jpg", width: 800, height: 600, shape: "rect" },
50
+ },
51
+ {
52
+ id: "img-2",
53
+ sort_id: 2,
54
+ url: "https://example.com/dog",
55
+ image: { url: "https://cdn.com/dog.jpg", width: 1024, height: 768, shape: "rect" },
56
+ },
57
+ ],
58
+ };
59
+ }
60
+
61
+ test("web-search: basic web search returns formatted text", async (t) => {
62
+ const resp = makeWebSearchResponse();
63
+ t.mock.method(SearchClient.prototype, "webSearch", async () => resp);
64
+
65
+ const result = await cozeWebSearchTool.execute("call-1", { query: "test" }, undefined as any, undefined as any, undefined as any);
66
+ const text = resultText(result);
67
+
68
+ assert.ok(text.includes("Coze web search: test"));
69
+ assert.ok(text.includes("Results (2)"));
70
+ assert.ok(text.includes("1. Result A"));
71
+ assert.ok(text.includes("URL: https://example.com/a"));
72
+ assert.ok(text.includes("Source: example.com"));
73
+ assert.ok(text.includes("Snippet A"));
74
+ assert.ok(text.includes("2. Result B"));
75
+ assert.ok(text.includes("Published: 2025-01-01"));
76
+ });
77
+
78
+ test("web-search: includes summary when present", async (t) => {
79
+ const resp = makeWebSearchResponse({ summary: "This is the summary" });
80
+ t.mock.method(SearchClient.prototype, "webSearch", async () => resp);
81
+
82
+ const result = await cozeWebSearchTool.execute("call-2", { query: "test", needSummary: true }, undefined as any, undefined as any, undefined as any);
83
+ const text = resultText(result);
84
+
85
+ assert.ok(text.includes("Summary: This is the summary"));
86
+ });
87
+
88
+ test("web-search: includes content when needContent is true", async (t) => {
89
+ const resp = makeWebSearchResponse();
90
+ resp.web_items[0].content = "Full page content here";
91
+ t.mock.method(SearchClient.prototype, "advancedSearch", async () => resp);
92
+
93
+ const result = await cozeWebSearchTool.execute("call-3", { query: "test", needContent: true }, undefined as any, undefined as any, undefined as any);
94
+ const text = resultText(result);
95
+
96
+ assert.ok(text.includes("Content:"));
97
+ assert.ok(text.includes("Full page content here"));
98
+ });
99
+
100
+ test("web-search: image search maps image items", async (t) => {
101
+ const resp = makeImageSearchResponse();
102
+ t.mock.method(SearchClient.prototype, "imageSearch", async () => resp);
103
+
104
+ const result = await cozeWebSearchTool.execute("call-4", { query: "cats", type: "image" }, undefined as any, undefined as any, undefined as any);
105
+ const text = resultText(result);
106
+
107
+ assert.ok(text.includes("1. Cat Photo"));
108
+ assert.ok(text.includes("Image: https://cdn.com/cat.jpg"));
109
+ assert.ok(text.includes("2. Untitled"));
110
+ assert.ok(text.includes("Image: https://cdn.com/dog.jpg"));
111
+ assert.equal((result as any).details.type, "image");
112
+ });
113
+
114
+ test("web-search: uses advancedSearch when filters are present", async (t) => {
115
+ const resp = makeWebSearchResponse();
116
+ const calls: string[] = [];
117
+ t.mock.method(SearchClient.prototype, "advancedSearch", async () => {
118
+ calls.push("advancedSearch");
119
+ return resp;
120
+ });
121
+ t.mock.method(SearchClient.prototype, "webSearch", async () => {
122
+ calls.push("webSearch");
123
+ return resp;
124
+ });
125
+
126
+ await cozeWebSearchTool.execute("call-5", { query: "test", timeRange: "1d" }, undefined as any, undefined as any, undefined as any);
127
+ assert.deepEqual(calls, ["advancedSearch"]);
128
+ });
129
+
130
+ test("web-search: uses webSearch when no filters present", async (t) => {
131
+ const resp = makeWebSearchResponse();
132
+ const calls: string[] = [];
133
+ t.mock.method(SearchClient.prototype, "advancedSearch", async () => {
134
+ calls.push("advancedSearch");
135
+ return resp;
136
+ });
137
+ t.mock.method(SearchClient.prototype, "webSearch", async () => {
138
+ calls.push("webSearch");
139
+ return resp;
140
+ });
141
+
142
+ await cozeWebSearchTool.execute("call-6", { query: "test" }, undefined as any, undefined as any, undefined as any);
143
+ assert.deepEqual(calls, ["webSearch"]);
144
+ });
145
+
146
+ test("web-search: uses advancedSearch when sites filter is set", async (t) => {
147
+ const resp = makeWebSearchResponse();
148
+ const calls: string[] = [];
149
+ t.mock.method(SearchClient.prototype, "advancedSearch", async () => {
150
+ calls.push("advancedSearch");
151
+ return resp;
152
+ });
153
+ t.mock.method(SearchClient.prototype, "webSearch", async () => {
154
+ calls.push("webSearch");
155
+ return resp;
156
+ });
157
+
158
+ await cozeWebSearchTool.execute("call-7", { query: "test", sites: "example.com" }, undefined as any, undefined as any, undefined as any);
159
+ assert.deepEqual(calls, ["advancedSearch"]);
160
+ });
161
+
162
+ test("web-search: returns error content on search failure", async (t) => {
163
+ t.mock.method(SearchClient.prototype, "webSearch", async () => {
164
+ throw new Error("API timeout");
165
+ });
166
+
167
+ const result = await cozeWebSearchTool.execute("call-8", { query: "test" }, undefined as any, undefined as any, undefined as any);
168
+
169
+ assert.ok(resultText(result).includes("Error: API timeout"));
170
+ assert.equal((result as any).details.error, true);
171
+ });
172
+
173
+ test("web-search: defaults count to 10 and type to web", async (t) => {
174
+ const captured: any[] = [];
175
+ t.mock.method(SearchClient.prototype, "webSearch", async (query: string, count: number, needSummary?: boolean) => {
176
+ captured.push({ query, count, needSummary });
177
+ return makeWebSearchResponse();
178
+ });
179
+
180
+ await cozeWebSearchTool.execute("call-9", { query: "hello" }, undefined as any, undefined as any, undefined as any);
181
+
182
+ assert.equal(captured[0].query, "hello");
183
+ assert.equal(captured[0].count, 10);
184
+ assert.equal((captured[0] as any).needSummary, undefined);
185
+ });
186
+
187
+ test("web-search: details contain correct metadata", async (t) => {
188
+ const resp = makeWebSearchResponse({ summary: "Sum" });
189
+ t.mock.method(SearchClient.prototype, "webSearch", async () => resp);
190
+
191
+ const result = await cozeWebSearchTool.execute("call-10", { query: "meta test" }, undefined as any, undefined as any, undefined as any);
192
+
193
+ assert.equal((result as any).details.query, "meta test");
194
+ assert.equal((result as any).details.type, "web");
195
+ assert.equal((result as any).details.summary, "Sum");
196
+ assert.equal((result as any).details.count, 2);
197
+ });
198
+
199
+ test("web-search: empty results produces correct output", async (t) => {
200
+ const resp: SearchResponse = { web_items: [], image_items: [] };
201
+ t.mock.method(SearchClient.prototype, "webSearch", async () => resp);
202
+
203
+ const result = await cozeWebSearchTool.execute("call-11", { query: "nothing" }, undefined as any, undefined as any, undefined as any);
204
+ const text = resultText(result);
205
+
206
+ assert.ok(text.includes("Results (0)"));
207
+ assert.equal((result as any).details.count, 0);
208
+ });
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "noEmit": true,
8
+ "skipLibCheck": true,
9
+ "verbatimModuleSyntax": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "allowSyntheticDefaultImports": true,
12
+ "resolveJsonModule": true,
13
+ "baseUrl": "."
14
+ },
15
+ "include": [
16
+ "src/**/*.ts",
17
+ "pi-resources/extensions/**/*.ts",
18
+ "tests/**/*.ts",
19
+ "types/**/*.d.ts"
20
+ ]
21
+ }
@@ -0,0 +1,113 @@
1
+ declare module "@larksuiteoapi/node-sdk" {
2
+ export enum AppType {
3
+ SelfBuild = "SelfBuild"
4
+ }
5
+
6
+ export enum Domain {
7
+ Feishu = "https://open.feishu.cn",
8
+ Lark = "https://open.larksuite.com"
9
+ }
10
+
11
+ export enum LoggerLevel {
12
+ warn = "warn"
13
+ }
14
+
15
+ export interface ClientOptions {
16
+ appId: string;
17
+ appSecret: string;
18
+ appType: AppType;
19
+ domain?: Domain | string;
20
+ }
21
+
22
+ export interface MessageReplyArgs {
23
+ path: {
24
+ message_id: string;
25
+ };
26
+ data: {
27
+ msg_type: string;
28
+ content: string;
29
+ };
30
+ }
31
+
32
+ export interface MessageReactionCreateArgs {
33
+ path: {
34
+ message_id: string;
35
+ };
36
+ data: {
37
+ reaction_type: {
38
+ emoji_type: string;
39
+ };
40
+ };
41
+ }
42
+
43
+ export interface MessageReactionDeleteArgs {
44
+ path: {
45
+ message_id: string;
46
+ reaction_id: string;
47
+ };
48
+ }
49
+
50
+ export class Client {
51
+ constructor(options: ClientOptions);
52
+ request(args: {
53
+ method: string;
54
+ url: string;
55
+ data: Record<string, never>;
56
+ }): Promise<{
57
+ bot?: {
58
+ open_id?: string;
59
+ };
60
+ data?: {
61
+ bot?: {
62
+ open_id?: string;
63
+ };
64
+ };
65
+ }>;
66
+ im: {
67
+ message: {
68
+ reply(args: MessageReplyArgs): Promise<unknown>;
69
+ };
70
+ messageReaction: {
71
+ create(args: MessageReactionCreateArgs): Promise<{
72
+ code?: number;
73
+ msg?: string;
74
+ data?: {
75
+ reaction_id?: string;
76
+ reaction_type?: {
77
+ emoji_type?: string;
78
+ };
79
+ };
80
+ }>;
81
+ delete(args: MessageReactionDeleteArgs): Promise<{
82
+ code?: number;
83
+ msg?: string;
84
+ data?: {
85
+ reaction_id?: string;
86
+ reaction_type?: {
87
+ emoji_type?: string;
88
+ };
89
+ };
90
+ }>;
91
+ };
92
+ };
93
+ }
94
+
95
+ export class EventDispatcher {
96
+ constructor(options: {
97
+ encryptKey: string;
98
+ verificationToken: string;
99
+ });
100
+ register(handlers: Record<string, (data: unknown) => Promise<void> | void>): void;
101
+ }
102
+
103
+ export class WSClient {
104
+ constructor(options: {
105
+ appId: string;
106
+ appSecret: string;
107
+ domain?: Domain | string;
108
+ loggerLevel?: LoggerLevel;
109
+ });
110
+ start(args: { eventDispatcher: EventDispatcher }): Promise<void>;
111
+ close(args?: { force?: boolean }): void;
112
+ }
113
+ }
@@ -197,9 +197,6 @@ importers:
197
197
  '@supabase/supabase-js':
198
198
  specifier: 2.95.3
199
199
  version: 2.95.3
200
- better-sqlite3:
201
- specifier: ^11.9.1
202
- version: 11.10.0
203
200
  coze-coding-dev-sdk:
204
201
  specifier: ^0.7.16
205
202
  version: 0.7.16(openai@6.16.0(ws@8.19.0)(zod@4.3.5))(ws@8.19.0)
@@ -234,9 +231,6 @@ importers:
234
231
  '@nestjs/schematics':
235
232
  specifier: ^10.2.3
236
233
  version: 10.2.3(chokidar@3.6.0)(typescript@5.9.3)
237
- '@types/better-sqlite3':
238
- specifier: ^7.6.13
239
- version: 7.6.13
240
234
  '@types/express':
241
235
  specifier: 5.0.6
242
236
  version: 5.0.6
@@ -15586,6 +15580,7 @@ snapshots:
15586
15580
  '@types/better-sqlite3@7.6.13':
15587
15581
  dependencies:
15588
15582
  '@types/node': 22.19.6
15583
+ optional: true
15589
15584
 
15590
15585
  '@types/body-parser@1.19.6':
15591
15586
  dependencies:
@@ -16921,6 +16916,7 @@ snapshots:
16921
16916
  dependencies:
16922
16917
  bindings: 1.5.0
16923
16918
  prebuild-install: 7.1.3
16919
+ optional: true
16924
16920
 
16925
16921
  big-integer@1.6.52: {}
16926
16922
 
@@ -16936,6 +16932,7 @@ snapshots:
16936
16932
  bindings@1.5.0:
16937
16933
  dependencies:
16938
16934
  file-uri-to-path: 1.0.0
16935
+ optional: true
16939
16936
 
16940
16937
  bl@1.2.3:
16941
16938
  dependencies:
@@ -17239,7 +17236,8 @@ snapshots:
17239
17236
  dependencies:
17240
17237
  readdirp: 5.0.0
17241
17238
 
17242
- chownr@1.1.4: {}
17239
+ chownr@1.1.4:
17240
+ optional: true
17243
17241
 
17244
17242
  chroma-js@2.6.0: {}
17245
17243
 
@@ -17735,6 +17733,7 @@ snapshots:
17735
17733
  decompress-response@6.0.0:
17736
17734
  dependencies:
17737
17735
  mimic-response: 3.1.0
17736
+ optional: true
17738
17737
 
17739
17738
  decompress-tar@4.1.1:
17740
17739
  dependencies:
@@ -18491,7 +18490,8 @@ snapshots:
18491
18490
 
18492
18491
  exif-parser@0.1.12: {}
18493
18492
 
18494
- expand-template@2.0.3: {}
18493
+ expand-template@2.0.3:
18494
+ optional: true
18495
18495
 
18496
18496
  express@4.21.2:
18497
18497
  dependencies:
@@ -18679,7 +18679,8 @@ snapshots:
18679
18679
 
18680
18680
  file-type@8.1.0: {}
18681
18681
 
18682
- file-uri-to-path@1.0.0: {}
18682
+ file-uri-to-path@1.0.0:
18683
+ optional: true
18683
18684
 
18684
18685
  filename-reserved-regex@2.0.0: {}
18685
18686
 
@@ -18963,7 +18964,8 @@ snapshots:
18963
18964
 
18964
18965
  git-clone@0.1.0: {}
18965
18966
 
18966
- github-from-package@0.0.0: {}
18967
+ github-from-package@0.0.0:
18968
+ optional: true
18967
18969
 
18968
18970
  glob-parent@5.1.2:
18969
18971
  dependencies:
@@ -20214,7 +20216,8 @@ snapshots:
20214
20216
 
20215
20217
  mimic-response@1.0.1: {}
20216
20218
 
20217
- mimic-response@3.1.0: {}
20219
+ mimic-response@3.1.0:
20220
+ optional: true
20218
20221
 
20219
20222
  min-document@2.19.2:
20220
20223
  dependencies:
@@ -20446,7 +20449,8 @@ snapshots:
20446
20449
 
20447
20450
  mkdir-p@0.0.7: {}
20448
20451
 
20449
- mkdirp-classic@0.5.3: {}
20452
+ mkdirp-classic@0.5.3:
20453
+ optional: true
20450
20454
 
20451
20455
  mkdirp@0.5.6:
20452
20456
  dependencies:
@@ -20503,7 +20507,8 @@ snapshots:
20503
20507
 
20504
20508
  nanoid@3.3.11: {}
20505
20509
 
20506
- napi-build-utils@2.0.0: {}
20510
+ napi-build-utils@2.0.0:
20511
+ optional: true
20507
20512
 
20508
20513
  natural-compare@1.4.0: {}
20509
20514
 
@@ -20545,6 +20550,7 @@ snapshots:
20545
20550
  node-abi@3.87.0:
20546
20551
  dependencies:
20547
20552
  semver: 7.7.4
20553
+ optional: true
20548
20554
 
20549
20555
  node-abort-controller@3.1.1: {}
20550
20556
 
@@ -21505,6 +21511,7 @@ snapshots:
21505
21511
  simple-get: 4.0.1
21506
21512
  tar-fs: 2.1.4
21507
21513
  tunnel-agent: 0.6.0
21514
+ optional: true
21508
21515
 
21509
21516
  prelude-ls@1.2.1: {}
21510
21517
 
@@ -22232,13 +22239,15 @@ snapshots:
22232
22239
 
22233
22240
  signal-exit@4.1.0: {}
22234
22241
 
22235
- simple-concat@1.0.1: {}
22242
+ simple-concat@1.0.1:
22243
+ optional: true
22236
22244
 
22237
22245
  simple-get@4.0.1:
22238
22246
  dependencies:
22239
22247
  decompress-response: 6.0.0
22240
22248
  once: 1.4.0
22241
22249
  simple-concat: 1.0.1
22250
+ optional: true
22242
22251
 
22243
22252
  simple-plist@1.3.1:
22244
22253
  dependencies:
@@ -22650,6 +22659,7 @@ snapshots:
22650
22659
  mkdirp-classic: 0.5.3
22651
22660
  pump: 3.0.3
22652
22661
  tar-stream: 2.2.0
22662
+ optional: true
22653
22663
 
22654
22664
  tar-stream@1.6.2:
22655
22665
  dependencies:
@@ -17,7 +17,6 @@
17
17
  "@nestjs/core": "^10.4.15",
18
18
  "@nestjs/platform-express": "^10.4.15",
19
19
  "@supabase/supabase-js": "2.95.3",
20
- "better-sqlite3": "^11.9.1",
21
20
  "coze-coding-dev-sdk": "^0.7.16",
22
21
  "dotenv": "^17.2.3",
23
22
  "drizzle-kit": "^0.31.8",
@@ -31,7 +30,6 @@
31
30
  "devDependencies": {
32
31
  "@nestjs/cli": "^10.4.9",
33
32
  "@nestjs/schematics": "^10.2.3",
34
- "@types/better-sqlite3": "^7.6.13",
35
33
  "@types/express": "5.0.6",
36
34
  "@types/node": "^22.10.2",
37
35
  "drizzle-kit": "^0.31.8",