@meetopenbot/claude-code 0.1.15 → 0.1.17

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 (2) hide show
  1. package/dist/index.js +119 -41
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -29,13 +29,12 @@ var resolveClaudeConfig = (context) => {
29
29
  import { execSync } from "node:child_process";
30
30
  import { existsSync } from "node:fs";
31
31
  import { join } from "node:path";
32
- import { query } from "@anthropic-ai/claude-agent-sdk";
33
32
  import {
34
- creditsErrorMessage,
35
33
  llmAuthNotConfiguredMessage,
36
34
  resolveByokApiKey,
37
35
  resolveCreditsAuthConfig as resolveCreditsAuthConfig2,
38
- isCloudMode
36
+ isCloudMode,
37
+ textReply as textReply2
39
38
  } from "@meetopenbot/plugin-sdk";
40
39
 
41
40
  // src/credits.ts
@@ -62,6 +61,109 @@ var buildCreditsAnthropicEnv = () => {
62
61
  import { threadSession } from "@meetopenbot/plugin-sdk";
63
62
  var claudeSession = threadSession("claudeSessionId");
64
63
 
64
+ // src/stream.ts
65
+ import { query } from "@anthropic-ai/claude-agent-sdk";
66
+ import {
67
+ createTextReplyBuffer,
68
+ creditsErrorMessage,
69
+ textReply
70
+ } from "@meetopenbot/plugin-sdk";
71
+ var extractText = (content) => {
72
+ if (typeof content === "string") return content;
73
+ if (!Array.isArray(content)) return "";
74
+ const parts = [];
75
+ for (const block of content) {
76
+ if (block && typeof block === "object" && block.type === "text") {
77
+ const text = block.text;
78
+ if (typeof text === "string" && text) parts.push(text);
79
+ }
80
+ }
81
+ return parts.join("\n");
82
+ };
83
+ var streamEventText = (event) => {
84
+ if (!event || typeof event !== "object") return "";
85
+ const delta = event.delta;
86
+ if (delta?.type === "text_delta" && typeof delta.text === "string") return delta.text;
87
+ return "";
88
+ };
89
+ var parseToolUse = (block) => {
90
+ if (!block || typeof block !== "object" || !("type" in block)) return null;
91
+ const type = block.type;
92
+ if (type !== "tool_use" && type !== "mcp_tool_use" && type !== "server_tool_use") return null;
93
+ const { id, name, input, server_name } = block;
94
+ if (typeof id !== "string" || typeof name !== "string") return null;
95
+ const title = typeof server_name === "string" ? `${server_name}: ${name}` : name;
96
+ return { type: "tool_call", id, name: title, input };
97
+ };
98
+ var parseToolResult = (block) => {
99
+ if (!block || typeof block !== "object" || !("type" in block)) return null;
100
+ const type = block.type;
101
+ if (type !== "tool_result" && type !== "mcp_tool_result") return null;
102
+ const { tool_use_id, content, is_error } = block;
103
+ if (typeof tool_use_id !== "string") return null;
104
+ return { type: "tool_result", id: tool_use_id, output: content, error: is_error };
105
+ };
106
+ var classifyClaudeEvent = (message) => {
107
+ if (message.type === "assistant") {
108
+ const content = message.message?.content;
109
+ const hints = [];
110
+ const text = extractText(content);
111
+ if (text) hints.push({ type: "text", text });
112
+ if (Array.isArray(content)) {
113
+ for (const block of content) {
114
+ const tool = parseToolUse(block);
115
+ if (tool) hints.push(tool);
116
+ }
117
+ }
118
+ return hints.length > 0 ? hints : { type: "skip" };
119
+ }
120
+ if (message.type === "user") {
121
+ const content = message.message?.content;
122
+ if (!Array.isArray(content)) return { type: "skip" };
123
+ const hints = [];
124
+ for (const block of content) {
125
+ const result = parseToolResult(block);
126
+ if (result) hints.push(result);
127
+ }
128
+ return hints.length > 0 ? hints : { type: "skip" };
129
+ }
130
+ if (message.type === "stream_event") {
131
+ const text = streamEventText(message.event);
132
+ return text ? { type: "delta", text } : { type: "skip" };
133
+ }
134
+ return { type: "skip" };
135
+ };
136
+ async function* runClaudeQuery(args) {
137
+ const { prompt, sdkOptions, resumeId, state, storage } = args;
138
+ const replies = createTextReplyBuffer({ groupId: "claude-code:tools" });
139
+ let lastSessionId = resumeId;
140
+ try {
141
+ for await (const message of query({ prompt, options: sdkOptions })) {
142
+ if ("session_id" in message && typeof message.session_id === "string") {
143
+ lastSessionId = message.session_id;
144
+ }
145
+ if (message.type === "result" && message.subtype !== "success") {
146
+ yield* replies.end();
147
+ const resultText = "result" in message && typeof message.result === "string" ? message.result : message.subtype;
148
+ yield textReply(
149
+ creditsErrorMessage(resultText, {
150
+ agentName: "Claude",
151
+ providerLabel: "Anthropic",
152
+ provider: "anthropic"
153
+ }) ?? resultText
154
+ );
155
+ return;
156
+ }
157
+ yield* replies.apply(classifyClaudeEvent(message));
158
+ }
159
+ yield* replies.end();
160
+ } finally {
161
+ if (lastSessionId && lastSessionId !== resumeId) {
162
+ await claudeSession.write(state, storage, lastSessionId);
163
+ }
164
+ }
165
+ }
166
+
65
167
  // src/system-prompt.ts
66
168
  var CLAUDE_CODE_SYSTEM_PROMPT = `
67
169
  You are Claude, an AI assistant powered by Anthropic's Claude Agent SDK (Claude Code).
@@ -83,23 +185,16 @@ var findClaudeExecutable = () => {
83
185
  }
84
186
  return void 0;
85
187
  };
86
- var extractText = (content) => {
87
- if (typeof content === "string") return content;
88
- if (!Array.isArray(content)) return "";
89
- const parts = [];
90
- for (const block of content) {
91
- if (block && typeof block === "object" && block.type === "text") {
92
- const text = block.text;
93
- if (typeof text === "string" && text) parts.push(text);
94
- }
95
- }
96
- return parts.join("\n");
97
- };
98
- async function runClaudeTurn({ prompt, handlerCtx, context }) {
188
+ async function* runClaudeTurn({
189
+ prompt,
190
+ handlerCtx,
191
+ context
192
+ }) {
99
193
  const byok = resolveByokApiKey("anthropic");
100
194
  const credits = !byok && isCloudMode() ? resolveCreditsAuthConfig2() : void 0;
101
195
  if (!byok && !credits) {
102
- return llmAuthNotConfiguredMessage("ANTHROPIC_API_KEY");
196
+ yield textReply2(llmAuthNotConfiguredMessage("ANTHROPIC_API_KEY"));
197
+ return;
103
198
  }
104
199
  const config = resolveClaudeConfig(context);
105
200
  const workingDir = handlerCtx.state.channelDetails?.cwd;
@@ -122,30 +217,13 @@ async function runClaudeTurn({ prompt, handlerCtx, context }) {
122
217
  ...workingDir ? { cwd: workingDir } : {},
123
218
  ...executablePath ? { pathToClaudeCodeExecutable: executablePath } : {}
124
219
  };
125
- let lastSessionId = resumeId;
126
- let text = "";
127
- for await (const message of query({ prompt, options: sdkOptions })) {
128
- if ("session_id" in message && typeof message.session_id === "string") {
129
- lastSessionId = message.session_id;
130
- }
131
- if (message.type === "assistant") {
132
- const next = extractText(message.message?.content);
133
- if (next) text = text ? `${text}
134
- ${next}` : next;
135
- }
136
- if (message.type === "result" && message.subtype !== "success") {
137
- const resultText = "result" in message && typeof message.result === "string" ? message.result : message.subtype;
138
- return creditsErrorMessage(resultText, {
139
- agentName: "Claude",
140
- providerLabel: "Anthropic",
141
- provider: "anthropic"
142
- }) ?? resultText;
143
- }
144
- }
145
- if (lastSessionId && lastSessionId !== resumeId) {
146
- await claudeSession.write(handlerCtx.state, context.storage, lastSessionId);
147
- }
148
- return text.trim();
220
+ yield* runClaudeQuery({
221
+ prompt,
222
+ sdkOptions,
223
+ resumeId,
224
+ state: handlerCtx.state,
225
+ storage: context.storage
226
+ });
149
227
  }
150
228
 
151
229
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meetopenbot/claude-code",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "type": "module",
5
5
  "description": "Claude Code plugin for OpenBot",
6
6
  "main": "./dist/index.js",
@@ -19,7 +19,7 @@
19
19
  ],
20
20
  "dependencies": {
21
21
  "@anthropic-ai/claude-agent-sdk": "^0.2.138",
22
- "@meetopenbot/plugin-sdk": "^0.3.0"
22
+ "@meetopenbot/plugin-sdk": "^0.5.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^20.10.1",