@bifrost-ai/engine-claude-code 0.0.3-build.1781903364429 → 0.1.1-build.1783540906154

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.
@@ -0,0 +1,13 @@
1
+ import { McpSdkServerConfigWithInstance } from "@anthropic-ai/claude-agent-sdk";
2
+ import { Engine, EngineContext, EngineResult } from "@bifrost-ai/engine";
3
+
4
+ //#region src/claude-code-engine.d.ts
5
+ type ToolkitConstructor = (context: EngineContext) => McpSdkServerConfigWithInstance;
6
+ declare class ClaudeCodeEngine implements Engine {
7
+ private toolkits;
8
+ registerToolkit(name: string, toolkit: McpSdkServerConfigWithInstance | ToolkitConstructor): void;
9
+ private resolveToolOptions;
10
+ execute(context: EngineContext, sessionId?: string): Promise<EngineResult>;
11
+ }
12
+ //#endregion
13
+ export { ClaudeCodeEngine, type ToolkitConstructor };
package/dist/index.mjs ADDED
@@ -0,0 +1,179 @@
1
+ import { query } from "@anthropic-ai/claude-agent-sdk";
2
+ import createDebug from "debug";
3
+ //#region src/claude-code-engine.ts
4
+ const debug = createDebug("bifrost:engine:claude-code");
5
+ const isSystemInit = (message) => message.type === "system" && message.subtype === "init";
6
+ const isResultMessage = (message) => message.type === "result";
7
+ const isResultSuccess = (message) => isResultMessage(message) && message.subtype === "success";
8
+ const isResultError = (message) => isResultMessage(message) && message.subtype !== "success";
9
+ const formatResultError = (message) => message.errors.length > 0 ? message.errors.join("; ") : message.subtype;
10
+ const formatToolInput = (input) => {
11
+ if (!input || typeof input !== "object") return String(input ?? "");
12
+ return Object.entries(input).slice(0, 3).map(([key, val]) => `${key}=${String(val)}`).join(", ");
13
+ };
14
+ const extractContent = (message) => {
15
+ const msg = message.message;
16
+ if (!msg?.content) return null;
17
+ const parts = [];
18
+ for (const block of msg.content) if (block.type === "text" && block.text) parts.push(block.text.replace(/\n/g, " "));
19
+ else if (block.type === "tool_use" && block.name) {
20
+ const args = formatToolInput(block.input);
21
+ parts.push(`ToolCall(${block.name}${args ? `, ${args}` : ""})`);
22
+ }
23
+ return parts.length > 0 ? parts.join(" | ") : null;
24
+ };
25
+ const extractToolResultPreview = (resultContent) => {
26
+ if (typeof resultContent === "string") return resultContent;
27
+ if (Array.isArray(resultContent)) return resultContent.map((block) => block.text ?? "").join("");
28
+ return "";
29
+ };
30
+ const extractUserPreview = (message) => {
31
+ const content = message.message?.content;
32
+ if (!content) return null;
33
+ if (typeof content === "string") return content.replace(/\n/g, " ");
34
+ const parts = [];
35
+ for (const block of content) if (block.type === "tool_result") {
36
+ const preview = extractToolResultPreview(block.content);
37
+ parts.push(`ToolResult(${block.tool_use_id ?? "?"}${preview ? `: ${preview.replace(/\n/g, " ")}` : ""})`);
38
+ } else if (block.type === "text" && block.text) parts.push(block.text.replace(/\n/g, " "));
39
+ return parts.length > 0 ? parts.join(" | ") : null;
40
+ };
41
+ const getMessagePreview = (message) => {
42
+ if (message.type === "assistant") return extractContent(message) ?? "";
43
+ else if (message.type === "user") return extractUserPreview(message) ?? "";
44
+ else if (message.type === "system") {
45
+ const sysMsg = message;
46
+ if (sysMsg.message) return sysMsg.message.replace(/\n/g, " ");
47
+ }
48
+ return "";
49
+ };
50
+ const promptSection = (name, body) => `<${name}>${body}</${name}>`;
51
+ const buildPrompt = (options) => {
52
+ const { agent, instructions } = options;
53
+ return [promptSection("AgentDefinition", agent.promptBody), promptSection("FeatureDefinition", instructions)].join("\n");
54
+ };
55
+ const buildStats = (resultData) => {
56
+ const { usage, duration_ms, total_cost_usd, num_turns } = resultData;
57
+ return {
58
+ durationMs: duration_ms,
59
+ inputTokens: usage.input_tokens,
60
+ outputTokens: usage.output_tokens,
61
+ cacheReadTokens: usage.cache_read_input_tokens ?? 0,
62
+ cacheCreationTokens: usage.cache_creation_input_tokens ?? 0,
63
+ totalCostUsd: total_cost_usd,
64
+ numTurns: num_turns
65
+ };
66
+ };
67
+ const mcpServerNamePattern = /^mcp__([^_]+(?:_[^_]+)*)__/;
68
+ var ClaudeCodeEngine = class {
69
+ toolkits = /* @__PURE__ */ new Map();
70
+ registerToolkit(name, toolkit) {
71
+ this.toolkits.set(name, toolkit);
72
+ }
73
+ resolveToolOptions(tools, context) {
74
+ const bareToolNames = [...new Set(tools.map((tool) => typeof tool === "string" ? tool.replace(/\(.*\)$/, "") : tool.name))];
75
+ const allowedTools = tools.flatMap((tool) => {
76
+ if (typeof tool === "string") return [tool];
77
+ if (tool.allow && tool.allow.length > 0) return tool.allow.map((pattern) => `${tool.name}(${pattern})`);
78
+ return [tool.name];
79
+ });
80
+ const denyPatterns = tools.flatMap((tool) => {
81
+ if (typeof tool === "string") return [];
82
+ return (tool.deny ?? []).map((pattern) => `${tool.name}(${pattern})`);
83
+ });
84
+ const toolOptions = {
85
+ tools: bareToolNames,
86
+ allowedTools,
87
+ ...denyPatterns.length > 0 && { disallowedTools: denyPatterns }
88
+ };
89
+ const activeServerNames = new Set(bareToolNames.map((toolName) => mcpServerNamePattern.exec(toolName)?.[1]).filter((serverName) => serverName !== null && serverName !== void 0));
90
+ debug("creating tools workingDir=%s", context.workingDir);
91
+ const mcpServers = {};
92
+ for (const name of activeServerNames) {
93
+ const entry = this.toolkits.get(name);
94
+ if (entry !== void 0 && entry !== null) mcpServers[name] = typeof entry === "function" ? entry(context) : entry;
95
+ }
96
+ debug("mcp tools created count=%s", Object.keys(mcpServers).length);
97
+ return {
98
+ bareToolNames,
99
+ toolOptions,
100
+ mcpServersOption: Object.keys(mcpServers).length > 0 ? { mcpServers } : void 0
101
+ };
102
+ }
103
+ async execute(context, sessionId) {
104
+ const { agent, instructions, workingDir } = context;
105
+ const { model, tools } = agent;
106
+ const prompt = sessionId ? instructions : buildPrompt({
107
+ agent,
108
+ instructions
109
+ });
110
+ debug("execute workingDir=%s sessionId=%s", workingDir, sessionId ?? "none");
111
+ debug("prompt: %s", prompt);
112
+ const { toolOptions, mcpServersOption } = this.resolveToolOptions(tools, context);
113
+ const options = {
114
+ cwd: workingDir,
115
+ permissionMode: "dontAsk",
116
+ ...sessionId && { resume: sessionId },
117
+ ...model && { model },
118
+ ...toolOptions,
119
+ ...mcpServersOption
120
+ };
121
+ if (!sessionId) debug("options: %o", options);
122
+ let lastMessage = null;
123
+ let resultData = void 0;
124
+ let errorResultData = void 0;
125
+ let returnedSessionId = sessionId;
126
+ try {
127
+ const queryGenerator = query({
128
+ prompt,
129
+ options
130
+ });
131
+ for await (const message of queryGenerator) {
132
+ const preview = getMessagePreview(message);
133
+ debug("message type=%s subtype=%s preview=%s", message.type, message.subtype ?? "-", preview ? `"${preview}..."` : "-");
134
+ if (isSystemInit(message)) {
135
+ returnedSessionId = message.session_id;
136
+ debug("session_id=%s", returnedSessionId);
137
+ }
138
+ if (isResultSuccess(message)) {
139
+ resultData = message;
140
+ lastMessage = resultData.result;
141
+ debug("result: %s", lastMessage);
142
+ } else if (isResultError(message)) {
143
+ errorResultData = message;
144
+ lastMessage = formatResultError(message);
145
+ debug("result error subtype=%s message=%s", message.subtype, lastMessage);
146
+ }
147
+ if (message.type === "assistant") {
148
+ const content = extractContent(message);
149
+ if (content) lastMessage = content;
150
+ }
151
+ }
152
+ } catch (error) {
153
+ debug("error: %o", error);
154
+ return {
155
+ success: false,
156
+ skipFulfill: false,
157
+ lastMessage: error instanceof Error ? error.message : String(error),
158
+ stats: null
159
+ };
160
+ }
161
+ if (errorResultData) return {
162
+ success: false,
163
+ skipFulfill: false,
164
+ lastMessage: lastMessage ?? "Claude execution failed",
165
+ stats: buildStats(errorResultData),
166
+ sessionId: returnedSessionId
167
+ };
168
+ const stats = resultData ? buildStats(resultData) : null;
169
+ return {
170
+ success: true,
171
+ skipFulfill: false,
172
+ lastMessage: lastMessage ?? "No response from Claude",
173
+ stats,
174
+ sessionId: returnedSessionId
175
+ };
176
+ }
177
+ };
178
+ //#endregion
179
+ export { ClaudeCodeEngine };
package/package.json CHANGED
@@ -1,24 +1,37 @@
1
1
  {
2
2
  "name": "@bifrost-ai/engine-claude-code",
3
- "version": "0.0.3-build.1781903364429",
4
- "description": "Claude Code Agent SDK engine for Orchestrator Framework",
5
- "type": "module",
3
+ "version": "0.1.1-build.1783540906154",
4
+ "description": "Claude Code Agent SDK engine for Bifrost orchestrator v2",
5
+ "license": "MIT",
6
6
  "files": [
7
7
  "dist"
8
8
  ],
9
- "main": "./dist/index.js",
10
- "types": "./dist/index.d.ts",
9
+ "type": "module",
11
10
  "exports": {
12
- ".": {
13
- "types": "./dist/index.d.ts",
14
- "import": "./dist/index.js"
15
- }
11
+ ".": "./dist/index.mjs",
12
+ "./package.json": "./package.json"
16
13
  },
17
- "scripts": {
18
- "build": "vite build"
14
+ "publishConfig": {
15
+ "access": "public"
19
16
  },
20
17
  "dependencies": {
21
- "@bifrost-ai/engine": "0.0.3-build.1781903364429",
22
- "@anthropic-ai/claude-agent-sdk": "^0.3.150"
18
+ "@anthropic-ai/claude-agent-sdk": "^0.3.150",
19
+ "@bifrost-ai/engine": "0.1.1-build.1783540906154",
20
+ "debug": "^4.4.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/debug": "^4.1.12",
24
+ "@types/node": "^25.6.2",
25
+ "@typescript/native-preview": "latest",
26
+ "bumpp": "^11.1.0",
27
+ "typescript": "^6.0.3",
28
+ "vite-plus": "^0.2.0",
29
+ "vitest-gwt": "^4.1.0"
30
+ },
31
+ "scripts": {
32
+ "build": "vp pack",
33
+ "dev": "vp pack --watch",
34
+ "test": "vp test",
35
+ "check": "vp check"
23
36
  }
24
- }
37
+ }
@@ -1,10 +0,0 @@
1
- import { Engine, EngineContext, EngineResult } from '@bifrost-ai/engine';
2
- import { McpSdkServerConfigWithInstance } from '@anthropic-ai/claude-agent-sdk';
3
- export type ToolkitConstructor = (context: EngineContext) => McpSdkServerConfigWithInstance;
4
- export declare class ClaudeCodeEngine implements Engine {
5
- private toolkits;
6
- registerToolkit(name: string, toolkit: McpSdkServerConfigWithInstance | ToolkitConstructor): void;
7
- private resolveToolOptions;
8
- execute(context: EngineContext, sessionId?: string): Promise<EngineResult>;
9
- }
10
- //# sourceMappingURL=claude-code-engine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude-code-engine.d.ts","sourceRoot":"","sources":["../src/claude-code-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,MAAM,EACN,aAAa,EACb,YAAY,EAEb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAML,KAAK,8BAA8B,EACpC,MAAM,gCAAgC,CAAC;AAkIxC,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,aAAa,KAAK,8BAA8B,CAAC;AAE5F,qBAAa,gBAAiB,YAAW,MAAM;IAC7C,OAAO,CAAC,QAAQ,CAA0E;IAEnF,eAAe,CACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,8BAA8B,GAAG,kBAAkB,GAC3D,IAAI;IAIP,OAAO,CAAC,kBAAkB;IAwDb,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;CAwFxF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=claude-code-engine.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"claude-code-engine.spec.d.ts","sourceRoot":"","sources":["../src/claude-code-engine.spec.ts"],"names":[],"mappings":""}
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export { ClaudeCodeEngine } from './claude-code-engine';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
package/dist/index.js DELETED
@@ -1,124 +0,0 @@
1
- import { query as e } from "@anthropic-ai/claude-agent-sdk";
2
- import t from "/home/devzeebo/git/bifrost/orchestrator/node_modules/debug/src/browser.js";
3
- //#region src/claude-code-engine.ts
4
- var n = t("bifrost:engine:claude-code"), r = (e) => e.type === "system" && e.subtype === "init", i = (e) => e.type === "result" && e.subtype === "success", a = (e) => !e || typeof e != "object" ? String(e ?? "") : Object.entries(e).slice(0, 3).map(([e, t]) => `${e}=${String(t)}`).join(", "), o = (e) => {
5
- let t = e.message;
6
- if (!t?.content) return null;
7
- let n = [];
8
- for (let e of t.content) if (e.type === "text" && e.text) n.push(e.text.replace(/\n/g, " "));
9
- else if (e.type === "tool_use" && e.name) {
10
- let t = a(e.input);
11
- n.push(`ToolCall(${e.name}${t ? `, ${t}` : ""})`);
12
- }
13
- return n.length > 0 ? n.join(" | ") : null;
14
- }, s = (e) => typeof e == "string" ? e : Array.isArray(e) ? e.map((e) => e.text ?? "").join("") : "", c = (e) => {
15
- let t = e.message?.content;
16
- if (!t) return null;
17
- if (typeof t == "string") return t.replace(/\n/g, " ");
18
- let n = [];
19
- for (let e of t) if (e.type === "tool_result") {
20
- let t = s(e.content);
21
- n.push(`ToolResult(${e.tool_use_id ?? "?"}${t ? `: ${t.replace(/\n/g, " ")}` : ""})`);
22
- } else e.type === "text" && e.text && n.push(e.text.replace(/\n/g, " "));
23
- return n.length > 0 ? n.join(" | ") : null;
24
- }, l = (e) => {
25
- if (e.type === "assistant") return o(e) ?? "";
26
- if (e.type === "user") return c(e) ?? "";
27
- if (e.type === "system") {
28
- let t = e;
29
- if (t.message) return t.message.replace(/\n/g, " ");
30
- }
31
- return "";
32
- }, u = (e, t) => `<${e}>${t}</${e}>`, d = (e) => {
33
- let { agent: t, metadata: n, instructions: r } = e;
34
- return [u("AgentDefinition", t.promptBody), u("FeatureDefinition", r)].join("\n");
35
- }, f = (e) => {
36
- let { usage: t, duration_ms: n, total_cost_usd: r, num_turns: i } = e;
37
- return {
38
- durationMs: n,
39
- inputTokens: t.input_tokens,
40
- outputTokens: t.output_tokens,
41
- cacheReadTokens: t.cache_read_input_tokens ?? 0,
42
- cacheCreationTokens: t.cache_creation_input_tokens ?? 0,
43
- totalCostUsd: r,
44
- numTurns: i
45
- };
46
- }, p = /^mcp__([^_]+(?:_[^_]+)*)__/, m = class {
47
- toolkits = /* @__PURE__ */ new Map();
48
- registerToolkit(e, t) {
49
- this.toolkits.set(e, t);
50
- }
51
- resolveToolOptions(e, t) {
52
- let r = [...new Set(e.map((e) => typeof e == "string" ? e.replace(/\(.*\)$/, "") : e.name))], i = e.flatMap((e) => typeof e == "string" ? [e] : (e.allow ?? []).map((t) => `${e.name}(${t})`)), a = e.flatMap((e) => typeof e == "string" ? [] : (e.deny ?? []).map((t) => `${e.name}(${t})`)), o = {
53
- tools: r,
54
- allowedTools: i,
55
- ...a.length > 0 && { denyTools: a }
56
- }, s = new Set(r.map((e) => p.exec(e)?.[1]).filter((e) => e != null));
57
- n("creating tools workingDir=%s", t.workingDir);
58
- let c = {};
59
- for (let e of s) {
60
- let n = this.toolkits.get(e);
61
- n != null && (c[e] = typeof n == "function" ? n(t) : n);
62
- }
63
- return n("mcp tools created count=%s", Object.keys(c).length), {
64
- bareToolNames: r,
65
- toolOptions: o,
66
- mcpServersOption: Object.keys(c).length > 0 ? { mcpServers: c } : void 0
67
- };
68
- }
69
- async execute(t, a) {
70
- let { agent: s, taskState: c, metadata: u, instructions: p, workingDir: m } = t, { model: h, tools: g } = s, _ = a ? p : d({
71
- agent: s,
72
- taskState: c,
73
- metadata: u,
74
- instructions: p
75
- });
76
- n("execute workingDir=%s sessionId=%s", m, a ?? "none"), n("prompt: %s", _);
77
- let { toolOptions: v, mcpServersOption: y } = this.resolveToolOptions(g, t), b = a ? {
78
- cwd: m,
79
- permissionMode: "dontAsk",
80
- resume: a,
81
- ...h && { model: h },
82
- ...v,
83
- ...y
84
- } : {
85
- cwd: m,
86
- permissionMode: "dontAsk",
87
- ...h && { model: h },
88
- ...v,
89
- ...y
90
- };
91
- a || n("options: %o", b);
92
- let x = null, S, C = a;
93
- try {
94
- let t = e({
95
- prompt: _,
96
- options: b
97
- });
98
- for await (let e of t) {
99
- let t = l(e);
100
- if (n("message type=%s subtype=%s preview=%s", e.type, e.subtype ?? "-", t ? `"${t}..."` : "-"), r(e) && (C = e.session_id, n("session_id=%s", C)), i(e) && (S = e, x = S.result, n("result: %s", x)), e.type === "assistant") {
101
- let t = o(e);
102
- t && (x = t);
103
- }
104
- }
105
- } catch (e) {
106
- return n("error: %o", e), {
107
- success: !1,
108
- skipFulfill: !1,
109
- lastMessage: e instanceof Error ? e.message : String(e),
110
- stats: null
111
- };
112
- }
113
- let w = S ? f(S) : null;
114
- return {
115
- success: !0,
116
- skipFulfill: !1,
117
- lastMessage: x ?? "No response from Claude",
118
- stats: w,
119
- sessionId: C
120
- };
121
- }
122
- };
123
- //#endregion
124
- export { m as ClaudeCodeEngine };