@tontoko/fast-playwright-mcp 0.0.4

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 (107) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +1047 -0
  3. package/cli.js +18 -0
  4. package/config.d.ts +124 -0
  5. package/index.d.ts +25 -0
  6. package/index.js +18 -0
  7. package/lib/actions.d.js +0 -0
  8. package/lib/batch/batch-executor.js +137 -0
  9. package/lib/browser-context-factory.js +252 -0
  10. package/lib/browser-server-backend.js +139 -0
  11. package/lib/config/constants.js +80 -0
  12. package/lib/config.js +405 -0
  13. package/lib/context.js +274 -0
  14. package/lib/diagnostics/common/diagnostic-base.js +63 -0
  15. package/lib/diagnostics/common/error-enrichment-utils.js +212 -0
  16. package/lib/diagnostics/common/index.js +56 -0
  17. package/lib/diagnostics/common/initialization-manager.js +210 -0
  18. package/lib/diagnostics/common/performance-tracker.js +132 -0
  19. package/lib/diagnostics/diagnostic-error.js +140 -0
  20. package/lib/diagnostics/diagnostic-level.js +123 -0
  21. package/lib/diagnostics/diagnostic-thresholds.js +347 -0
  22. package/lib/diagnostics/element-discovery.js +441 -0
  23. package/lib/diagnostics/enhanced-error-handler.js +376 -0
  24. package/lib/diagnostics/error-enrichment.js +157 -0
  25. package/lib/diagnostics/frame-reference-manager.js +179 -0
  26. package/lib/diagnostics/page-analyzer.js +639 -0
  27. package/lib/diagnostics/parallel-page-analyzer.js +129 -0
  28. package/lib/diagnostics/resource-manager.js +134 -0
  29. package/lib/diagnostics/smart-config.js +482 -0
  30. package/lib/diagnostics/smart-handle.js +118 -0
  31. package/lib/diagnostics/unified-system.js +717 -0
  32. package/lib/extension/cdp-relay.js +486 -0
  33. package/lib/extension/extension-context-factory.js +74 -0
  34. package/lib/extension/main.js +41 -0
  35. package/lib/file-utils.js +42 -0
  36. package/lib/generate-keys.js +75 -0
  37. package/lib/http-server.js +50 -0
  38. package/lib/in-process-client.js +64 -0
  39. package/lib/index.js +48 -0
  40. package/lib/javascript.js +90 -0
  41. package/lib/log.js +33 -0
  42. package/lib/loop/loop-claude.js +247 -0
  43. package/lib/loop/loop-open-ai.js +222 -0
  44. package/lib/loop/loop.js +174 -0
  45. package/lib/loop/main.js +46 -0
  46. package/lib/loopTools/context.js +76 -0
  47. package/lib/loopTools/main.js +65 -0
  48. package/lib/loopTools/perform.js +40 -0
  49. package/lib/loopTools/snapshot.js +37 -0
  50. package/lib/loopTools/tool.js +26 -0
  51. package/lib/manual-promise.js +125 -0
  52. package/lib/mcp/in-process-transport.js +91 -0
  53. package/lib/mcp/proxy-backend.js +127 -0
  54. package/lib/mcp/server.js +123 -0
  55. package/lib/mcp/transport.js +159 -0
  56. package/lib/package.js +28 -0
  57. package/lib/program.js +82 -0
  58. package/lib/response.js +493 -0
  59. package/lib/schemas/expectation.js +152 -0
  60. package/lib/session-log.js +210 -0
  61. package/lib/tab.js +417 -0
  62. package/lib/tools/base-tool-handler.js +141 -0
  63. package/lib/tools/batch-execute.js +150 -0
  64. package/lib/tools/common.js +65 -0
  65. package/lib/tools/console.js +60 -0
  66. package/lib/tools/diagnose/diagnose-analysis-runner.js +101 -0
  67. package/lib/tools/diagnose/diagnose-config-handler.js +130 -0
  68. package/lib/tools/diagnose/diagnose-report-builder.js +394 -0
  69. package/lib/tools/diagnose.js +147 -0
  70. package/lib/tools/dialogs.js +57 -0
  71. package/lib/tools/evaluate.js +67 -0
  72. package/lib/tools/files.js +53 -0
  73. package/lib/tools/find-elements.js +307 -0
  74. package/lib/tools/install.js +60 -0
  75. package/lib/tools/keyboard.js +93 -0
  76. package/lib/tools/mouse.js +110 -0
  77. package/lib/tools/navigate.js +82 -0
  78. package/lib/tools/network.js +50 -0
  79. package/lib/tools/pdf.js +46 -0
  80. package/lib/tools/screenshot.js +113 -0
  81. package/lib/tools/snapshot.js +158 -0
  82. package/lib/tools/tabs.js +97 -0
  83. package/lib/tools/tool.js +47 -0
  84. package/lib/tools/utils.js +131 -0
  85. package/lib/tools/wait.js +64 -0
  86. package/lib/tools.js +65 -0
  87. package/lib/types/batch.js +47 -0
  88. package/lib/types/diff.js +0 -0
  89. package/lib/types/performance.js +0 -0
  90. package/lib/types/threshold-base.js +0 -0
  91. package/lib/utils/array-utils.js +44 -0
  92. package/lib/utils/code-deduplication-utils.js +141 -0
  93. package/lib/utils/common-formatters.js +252 -0
  94. package/lib/utils/console-filter.js +64 -0
  95. package/lib/utils/diagnostic-report-utils.js +178 -0
  96. package/lib/utils/diff-formatter.js +126 -0
  97. package/lib/utils/disposable-manager.js +135 -0
  98. package/lib/utils/error-handler-middleware.js +77 -0
  99. package/lib/utils/image-processor.js +137 -0
  100. package/lib/utils/index.js +92 -0
  101. package/lib/utils/report-builder.js +189 -0
  102. package/lib/utils/request-logger.js +82 -0
  103. package/lib/utils/response-diff-detector.js +150 -0
  104. package/lib/utils/section-builder.js +62 -0
  105. package/lib/utils/tool-patterns.js +153 -0
  106. package/lib/utils.js +46 -0
  107. package/package.json +77 -0
@@ -0,0 +1,75 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/generate-keys.ts
21
+ import { generateKeyPairSync, randomBytes } from "node:crypto";
22
+ function generateMockKeyPair() {
23
+ const { privateKey: privateKeyObj, publicKey } = generateKeyPairSync("rsa", {
24
+ modulusLength: 2048,
25
+ publicKeyEncoding: {
26
+ type: "spki",
27
+ format: "pem"
28
+ },
29
+ privateKeyEncoding: {
30
+ type: "pkcs8",
31
+ format: "pem"
32
+ }
33
+ });
34
+ const privateKey = privateKeyObj;
35
+ const serialNumber = randomBytes(16).toString("hex");
36
+ const currentDate = new Date;
37
+ const expiryDate = new Date(currentDate.getTime() + 365 * 24 * 60 * 60 * 1000);
38
+ const certificate = generateSelfSignedCert(publicKey, serialNumber, currentDate, expiryDate);
39
+ return {
40
+ privateKey,
41
+ certificate
42
+ };
43
+ }
44
+ function loadOrGenerateKeys() {
45
+ const envPrivateKey = process.env.TEST_PRIVATE_KEY;
46
+ const envCertificate = process.env.TEST_CERTIFICATE;
47
+ if (envPrivateKey && envCertificate) {
48
+ return {
49
+ privateKey: envPrivateKey,
50
+ certificate: envCertificate
51
+ };
52
+ }
53
+ return getBackupTestKeys();
54
+ }
55
+ function getBackupTestKeys() {
56
+ return generateMockKeyPair();
57
+ }
58
+ function generateSelfSignedCert(publicKey, serialNumber, notBefore, notAfter) {
59
+ const mockCert = `-----BEGIN CERTIFICATE-----
60
+ ${Buffer.from(`
61
+ Mock Certificate for Testing
62
+ Serial: ${serialNumber}
63
+ Valid from: ${notBefore.toISOString()}
64
+ Valid to: ${notAfter.toISOString()}
65
+ ${publicKey}
66
+ `).toString("base64").match(/.{1,64}/g)?.join(`
67
+ `) || ""}
68
+ -----END CERTIFICATE-----`;
69
+ return mockCert;
70
+ }
71
+ export {
72
+ loadOrGenerateKeys,
73
+ getBackupTestKeys,
74
+ generateMockKeyPair
75
+ };
@@ -0,0 +1,50 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/http-server.ts
21
+ import assert from "node:assert/strict";
22
+ import http from "node:http";
23
+ async function startHttpServer(config) {
24
+ const { host, port } = config;
25
+ const httpServer = http.createServer();
26
+ await new Promise((resolve, reject) => {
27
+ httpServer.on("error", reject);
28
+ httpServer.listen(port, host, () => {
29
+ resolve();
30
+ httpServer.removeListener("error", reject);
31
+ });
32
+ });
33
+ return httpServer;
34
+ }
35
+ function httpAddressToString(address) {
36
+ assert(address, "Could not bind server socket");
37
+ if (typeof address === "string") {
38
+ return address;
39
+ }
40
+ const resolvedPort = address.port;
41
+ let resolvedHost = address.family === "IPv4" ? address.address : `[${address.address}]`;
42
+ if (resolvedHost === "0.0.0.0" || resolvedHost === "[::]") {
43
+ resolvedHost = "localhost";
44
+ }
45
+ return `http://${resolvedHost}:${resolvedPort}`;
46
+ }
47
+ export {
48
+ startHttpServer,
49
+ httpAddressToString
50
+ };
@@ -0,0 +1,64 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/in-process-client.ts
21
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
22
+ import { ListRootsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
23
+ import { BrowserServerBackend } from "./browser-server-backend.js";
24
+ import { InProcessTransport } from "./mcp/in-process-transport.js";
25
+ import { createServer } from "./mcp/server.js";
26
+ import { packageJSON } from "./package.js";
27
+
28
+ class InProcessClientFactory {
29
+ name;
30
+ description;
31
+ _contextFactory;
32
+ _config;
33
+ constructor(contextFactory, config) {
34
+ this.name = contextFactory.name;
35
+ this.description = contextFactory.description;
36
+ this._contextFactory = contextFactory;
37
+ this._config = config;
38
+ }
39
+ async create(server) {
40
+ const client = new Client(server.getClientVersion() ?? {
41
+ name: this.name,
42
+ version: packageJSON.version
43
+ });
44
+ const clientCapabilities = server.getClientCapabilities();
45
+ if (clientCapabilities) {
46
+ client.registerCapabilities(clientCapabilities);
47
+ }
48
+ if (clientCapabilities?.roots) {
49
+ client.setRequestHandler(ListRootsRequestSchema, async () => {
50
+ return await server.listRoots();
51
+ });
52
+ }
53
+ const backend = new BrowserServerBackend(this._config, [
54
+ this._contextFactory
55
+ ]);
56
+ const delegate = createServer(backend, false);
57
+ await client.connect(new InProcessTransport(delegate));
58
+ await client.ping();
59
+ return client;
60
+ }
61
+ }
62
+ export {
63
+ InProcessClientFactory
64
+ };
package/lib/index.js ADDED
@@ -0,0 +1,48 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/index.ts
21
+ import { contextFactory } from "./browser-context-factory.js";
22
+ import { BrowserServerBackend } from "./browser-server-backend.js";
23
+ import { resolveConfig } from "./config.js";
24
+ import { createServer } from "./mcp/server.js";
25
+ function createConnection(userConfig = {}, contextGetter) {
26
+ const config = resolveConfig(userConfig);
27
+ const factory = contextGetter ? new SimpleBrowserContextFactory(contextGetter) : contextFactory(config);
28
+ return createServer(new BrowserServerBackend(config, [factory]), false);
29
+ }
30
+
31
+ class SimpleBrowserContextFactory {
32
+ name = "custom";
33
+ description = "Connect to a browser using a custom context getter";
34
+ _contextGetter;
35
+ constructor(contextGetter) {
36
+ this._contextGetter = contextGetter;
37
+ }
38
+ async createContext() {
39
+ const browserContext = await this._contextGetter();
40
+ return {
41
+ browserContext,
42
+ close: () => browserContext.close()
43
+ };
44
+ }
45
+ }
46
+ export {
47
+ createConnection
48
+ };
@@ -0,0 +1,90 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/javascript.ts
21
+ function escapeWithQuotes(text, char = "'") {
22
+ const stringified = JSON.stringify(text);
23
+ const escapedText = extractEscapedContent(stringified);
24
+ return wrapWithCharacter(escapedText, char);
25
+ }
26
+ function extractEscapedContent(stringified) {
27
+ return stringified.substring(1, stringified.length - 1).replace(/\\"/g, '"');
28
+ }
29
+ function wrapWithCharacter(text, char) {
30
+ const replacements = {
31
+ "'": "'",
32
+ '"': '"',
33
+ "`": "`"
34
+ };
35
+ const replacement = replacements[char];
36
+ if (!replacement) {
37
+ throw new Error("Invalid escape char");
38
+ }
39
+ let result = text;
40
+ if (char === "'") {
41
+ result = text.replaceAll("'", "'");
42
+ } else if (char === '"') {
43
+ result = text.replaceAll('"', '"');
44
+ } else if (char === "`") {
45
+ result = text.replaceAll("`", "`");
46
+ }
47
+ return char + result + char;
48
+ }
49
+ function quote(text) {
50
+ return escapeWithQuotes(text, "'");
51
+ }
52
+ function formatObject(value, indent = " ") {
53
+ if (typeof value === "string") {
54
+ return quote(value);
55
+ }
56
+ if (Array.isArray(value)) {
57
+ return formatArray(value);
58
+ }
59
+ if (typeof value === "object" && value !== null) {
60
+ return formatObjectValue(value, indent);
61
+ }
62
+ return String(value);
63
+ }
64
+ function formatArray(arr) {
65
+ return `[${arr.map((o) => formatObject(o)).join(", ")}]`;
66
+ }
67
+ function formatObjectValue(obj, indent) {
68
+ const keys = getValidObjectKeys(obj);
69
+ if (keys.length === 0) {
70
+ return "{}";
71
+ }
72
+ return buildObjectString(obj, keys, indent);
73
+ }
74
+ function getValidObjectKeys(obj) {
75
+ return Object.keys(obj).filter((key) => obj[key] !== undefined).sort((a, b) => a.localeCompare(b, "en", { numeric: true }));
76
+ }
77
+ function buildObjectString(obj, keys, indent) {
78
+ const tokens = keys.map((key) => `${key}: ${formatObject(obj[key])}`);
79
+ const separator = `,
80
+ ${indent}`;
81
+ const tokensJoined = tokens.join(separator);
82
+ return `{
83
+ ${indent}${tokensJoined}
84
+ }`;
85
+ }
86
+ export {
87
+ quote,
88
+ formatObject,
89
+ escapeWithQuotes
90
+ };
package/lib/log.js ADDED
@@ -0,0 +1,33 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/log.ts
21
+ import debug from "debug";
22
+ var errorsDebug = debug("pw:mcp:errors");
23
+ var requestsDebug = debug("pw:mcp:requests");
24
+ function logUnhandledError(error) {
25
+ errorsDebug(error);
26
+ }
27
+ var testDebug = debug("pw:mcp:test");
28
+ var requestDebug = requestsDebug;
29
+ export {
30
+ testDebug,
31
+ requestDebug,
32
+ logUnhandledError
33
+ };
@@ -0,0 +1,247 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
20
+ // src/loop/loop-claude.ts
21
+ var model = "claude-sonnet-4-20250514";
22
+
23
+ class ClaudeDelegate {
24
+ _anthropic;
25
+ async anthropic() {
26
+ if (!this._anthropic) {
27
+ const anthropic = await import("@anthropic-ai/sdk");
28
+ this._anthropic = new anthropic.Anthropic;
29
+ }
30
+ return this._anthropic;
31
+ }
32
+ createConversation(task, tools, oneShot) {
33
+ const llmTools = tools.map((tool) => ({
34
+ name: tool.name,
35
+ description: tool.description ?? "",
36
+ inputSchema: tool.inputSchema
37
+ }));
38
+ if (!oneShot) {
39
+ llmTools.push({
40
+ name: "done",
41
+ description: "Call this tool when the task is complete.",
42
+ inputSchema: {
43
+ type: "object",
44
+ properties: {}
45
+ }
46
+ });
47
+ }
48
+ return {
49
+ messages: [
50
+ {
51
+ role: "user",
52
+ content: task
53
+ }
54
+ ],
55
+ tools: llmTools
56
+ };
57
+ }
58
+ async makeApiCall(conversation) {
59
+ const formattedData = this.formatConversationData(conversation);
60
+ const response = await this.callClaudeApi(formattedData.claudeMessages, formattedData.claudeTools);
61
+ return this.processApiResponse(conversation, response);
62
+ }
63
+ processApiResponse(conversation, response) {
64
+ return this.processResponseAndUpdateConversation(conversation, response);
65
+ }
66
+ processResponseAndUpdateConversation(conversation, response) {
67
+ const llmToolCalls = this.extractToolCallsFromResponse(response);
68
+ this.addAssistantMessageToConversation(conversation, response, llmToolCalls);
69
+ return llmToolCalls;
70
+ }
71
+ formatConversationData(conversation) {
72
+ return {
73
+ claudeMessages: this.convertMessagesToClaudeFormat(conversation.messages),
74
+ claudeTools: this.convertToolsToClaudeFormat(conversation.tools)
75
+ };
76
+ }
77
+ convertMessagesToClaudeFormat(messages) {
78
+ return this.buildClaudeMessagesFromConversation(messages);
79
+ }
80
+ buildClaudeMessagesFromConversation(messages) {
81
+ const claudeMessages = [];
82
+ for (const message of messages) {
83
+ this.processMessageByType(claudeMessages, message);
84
+ }
85
+ return claudeMessages;
86
+ }
87
+ processMessageByType(claudeMessages, message) {
88
+ this.delegateMessageProcessing(claudeMessages, message);
89
+ }
90
+ delegateMessageProcessing(claudeMessages, message) {
91
+ switch (message.role) {
92
+ case "user":
93
+ this.addUserMessage(claudeMessages, message);
94
+ break;
95
+ case "assistant":
96
+ this.addAssistantMessage(claudeMessages, message);
97
+ break;
98
+ case "tool":
99
+ this.addToolResultMessage(claudeMessages, message);
100
+ break;
101
+ default:
102
+ break;
103
+ }
104
+ }
105
+ addUserMessage(claudeMessages, message) {
106
+ if (message.role === "user") {
107
+ claudeMessages.push({
108
+ role: "user",
109
+ content: message.content
110
+ });
111
+ }
112
+ }
113
+ addAssistantMessage(claudeMessages, message) {
114
+ if (message.role !== "assistant") {
115
+ return;
116
+ }
117
+ const content = this.buildAssistantContent(message);
118
+ claudeMessages.push({
119
+ role: "assistant",
120
+ content
121
+ });
122
+ }
123
+ buildAssistantContent(message) {
124
+ const content = [];
125
+ this.populateContentBlocks(content, message);
126
+ return content;
127
+ }
128
+ populateContentBlocks(content, message) {
129
+ this.addTextContentIfPresent(content, message.content);
130
+ this.addToolCallsIfPresent(content, message);
131
+ }
132
+ addTextContentIfPresent(content, textContent) {
133
+ if (!textContent) {
134
+ return;
135
+ }
136
+ content.push({
137
+ type: "text",
138
+ text: textContent,
139
+ citations: []
140
+ });
141
+ }
142
+ addToolCallsIfPresent(content, message) {
143
+ if (message.role !== "assistant" || !message.toolCalls) {
144
+ return;
145
+ }
146
+ this.addToolCallsToContent(content, message.toolCalls);
147
+ }
148
+ addToolCallsToContent(content, toolCalls) {
149
+ for (const toolCall of toolCalls) {
150
+ content.push({
151
+ type: "tool_use",
152
+ id: toolCall.id,
153
+ name: toolCall.name,
154
+ input: toolCall.arguments
155
+ });
156
+ }
157
+ }
158
+ addToolResultMessage(claudeMessages, message) {
159
+ if (message.role !== "tool") {
160
+ return;
161
+ }
162
+ const toolResult = this.createToolResultBlock(message);
163
+ this.appendToolResultToMessages(claudeMessages, toolResult);
164
+ }
165
+ createToolResultBlock(message) {
166
+ return {
167
+ type: "tool_result",
168
+ tool_use_id: message.toolCallId,
169
+ content: message.content,
170
+ is_error: message.isError
171
+ };
172
+ }
173
+ appendToolResultToMessages(claudeMessages, toolResult) {
174
+ const lastMessage = claudeMessages.at(-1);
175
+ this.handleToolResultAppending(claudeMessages, lastMessage, toolResult);
176
+ }
177
+ handleToolResultAppending(claudeMessages, lastMessage, toolResult) {
178
+ if (this.canAddToExistingToolResults(lastMessage)) {
179
+ this.addToExistingMessage(lastMessage, toolResult);
180
+ } else {
181
+ this.createNewToolResultMessage(claudeMessages, toolResult);
182
+ }
183
+ }
184
+ addToExistingMessage(lastMessage, toolResult) {
185
+ lastMessage.content.push(toolResult);
186
+ }
187
+ createNewToolResultMessage(claudeMessages, toolResult) {
188
+ claudeMessages.push({
189
+ role: "user",
190
+ content: [toolResult]
191
+ });
192
+ }
193
+ canAddToExistingToolResults(lastMessage) {
194
+ return !!(lastMessage && lastMessage.role === "user" && Array.isArray(lastMessage.content));
195
+ }
196
+ convertToolsToClaudeFormat(tools) {
197
+ return tools.map((tool) => ({
198
+ name: tool.name,
199
+ description: tool.description,
200
+ input_schema: tool.inputSchema
201
+ }));
202
+ }
203
+ async callClaudeApi(claudeMessages, claudeTools) {
204
+ const anthropic = await this.anthropic();
205
+ return await anthropic.messages.create({
206
+ model,
207
+ max_tokens: 1e4,
208
+ messages: claudeMessages,
209
+ tools: claudeTools
210
+ });
211
+ }
212
+ extractToolCallsFromResponse(response) {
213
+ const toolCalls = response.content.filter((block) => block.type === "tool_use");
214
+ return toolCalls.map((toolCall) => ({
215
+ name: toolCall.name,
216
+ arguments: toolCall.input,
217
+ id: toolCall.id
218
+ }));
219
+ }
220
+ addAssistantMessageToConversation(conversation, response, llmToolCalls) {
221
+ const textContent = response.content.filter((block) => block.type === "text").map((block) => block.text).join("");
222
+ conversation.messages.push({
223
+ role: "assistant",
224
+ content: textContent,
225
+ toolCalls: llmToolCalls.length > 0 ? llmToolCalls : undefined
226
+ });
227
+ }
228
+ addToolResults(conversation, results) {
229
+ for (const result of results) {
230
+ conversation.messages.push({
231
+ role: "tool",
232
+ toolCallId: result.toolCallId,
233
+ content: result.content,
234
+ isError: result.isError
235
+ });
236
+ }
237
+ }
238
+ checkDoneToolCall(toolCall) {
239
+ if (toolCall.name === "done") {
240
+ return toolCall.arguments.result;
241
+ }
242
+ return null;
243
+ }
244
+ }
245
+ export {
246
+ ClaudeDelegate
247
+ };