@meetopenbot/claude-code 0.1.12 → 0.1.13

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,4 @@
1
+ import type { Plugin } from '@meetopenbot/plugin-sdk';
2
+ declare const plugin: Plugin;
3
+ export { plugin };
4
+ export default plugin;
package/dist/index.js CHANGED
@@ -43,7 +43,7 @@ async function resolveModelConfigField() {
43
43
  import { execSync } from "node:child_process";
44
44
  import { existsSync as existsSync2, readlinkSync as readlinkSync2, statSync as statSync2 } from "node:fs";
45
45
 
46
- // node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
46
+ // ../../node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.2.141_@cfworker+json-schema@4.1.1_zod@4.4.3/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
47
47
  import { createRequire as $S } from "node:module";
48
48
  import { execFile as E6$ } from "child_process";
49
49
  import { randomUUID as rz } from "crypto";
@@ -19370,15 +19370,15 @@ function Z_($, Q) {
19370
19370
  return null;
19371
19371
  }
19372
19372
 
19373
- // node_modules/@meetopenbot/plugin-sdk/dist/index.js
19373
+ // ../plugin-sdk/dist/index.js
19374
19374
  import { z } from "zod";
19375
19375
 
19376
- // node_modules/@meetopenbot/plugin-sdk/dist/plugin.js
19376
+ // ../plugin-sdk/dist/plugin.js
19377
19377
  function definePlugin(definition) {
19378
19378
  return definition;
19379
19379
  }
19380
19380
 
19381
- // node_modules/@meetopenbot/plugin-sdk/dist/helpers.js
19381
+ // ../plugin-sdk/dist/helpers.js
19382
19382
  function shouldHandleInvoke(event, agentId) {
19383
19383
  const routedTo = event.data?.agentId;
19384
19384
  return !(typeof routedTo === "string" && routedTo && routedTo !== agentId);
@@ -19394,6 +19394,17 @@ function agentOutput(args) {
19394
19394
  }
19395
19395
  };
19396
19396
  }
19397
+ function toolTraceWidget(args) {
19398
+ return {
19399
+ kind: "message",
19400
+ display: "collapsed",
19401
+ widgetId: args.widgetId,
19402
+ groupId: args.groupId,
19403
+ title: args.title,
19404
+ ...args.body ? { body: args.body } : {},
19405
+ ...args.state ? { state: args.state } : {}
19406
+ };
19407
+ }
19397
19408
  function uiWidget(args) {
19398
19409
  return {
19399
19410
  type: "client:ui:widget",
@@ -19406,6 +19417,275 @@ function uiWidget(args) {
19406
19417
  };
19407
19418
  }
19408
19419
 
19420
+ // ../plugin-sdk/dist/diff.js
19421
+ import { spawnSync } from "node:child_process";
19422
+ import { readFileSync as readFileSync2 } from "node:fs";
19423
+ import { join } from "node:path";
19424
+ var MAX_DIFF_FILES = 40;
19425
+ var MAX_DIFF_PATCH_CHARS = 48e3;
19426
+ var LANG_BY_EXT = {
19427
+ ts: "typescript",
19428
+ tsx: "tsx",
19429
+ js: "javascript",
19430
+ jsx: "jsx",
19431
+ mjs: "javascript",
19432
+ cjs: "javascript",
19433
+ py: "python",
19434
+ go: "go",
19435
+ rs: "rust",
19436
+ rb: "ruby",
19437
+ java: "java",
19438
+ kt: "kotlin",
19439
+ swift: "swift",
19440
+ cs: "csharp",
19441
+ cpp: "cpp",
19442
+ cc: "cpp",
19443
+ cxx: "cpp",
19444
+ c: "c",
19445
+ h: "c",
19446
+ hpp: "cpp",
19447
+ md: "markdown",
19448
+ json: "json",
19449
+ css: "css",
19450
+ scss: "scss",
19451
+ html: "html",
19452
+ yml: "yaml",
19453
+ yaml: "yaml",
19454
+ toml: "toml",
19455
+ sh: "bash",
19456
+ bash: "bash",
19457
+ zsh: "bash",
19458
+ sql: "sql"
19459
+ };
19460
+ var WRITE_TOOLS = /^(write|write_file|notebookedit|notebook_edit)$/i;
19461
+ var EDIT_TOOLS = /^(edit|strreplace|str_replace|edit_file|replace)$/i;
19462
+ function isRecord(value) {
19463
+ return typeof value === "object" && value !== null && !Array.isArray(value);
19464
+ }
19465
+ function asString(value) {
19466
+ return typeof value === "string" && value.length > 0 ? value : void 0;
19467
+ }
19468
+ function languageFromPath(path) {
19469
+ const base = path.split("/").pop() ?? path;
19470
+ const ext = base.includes(".") ? base.slice(base.lastIndexOf(".") + 1).toLowerCase() : "";
19471
+ return LANG_BY_EXT[ext];
19472
+ }
19473
+ function countPatchStats(patch) {
19474
+ let additions = 0;
19475
+ let deletions = 0;
19476
+ for (const line of patch.split("\n")) {
19477
+ if (line.startsWith("+") && !line.startsWith("+++"))
19478
+ additions += 1;
19479
+ else if (line.startsWith("-") && !line.startsWith("---"))
19480
+ deletions += 1;
19481
+ }
19482
+ return { additions, deletions };
19483
+ }
19484
+ function capPatch(patch) {
19485
+ if (patch.length <= MAX_DIFF_PATCH_CHARS)
19486
+ return { patch };
19487
+ return { patch: patch.slice(0, MAX_DIFF_PATCH_CHARS), truncated: true };
19488
+ }
19489
+ function summarizeDiffFiles(files) {
19490
+ const additions = files.reduce((sum, file) => sum + (file.additions ?? 0), 0);
19491
+ const deletions = files.reduce((sum, file) => sum + (file.deletions ?? 0), 0);
19492
+ const fileLabel = files.length === 1 ? "1 file" : `${files.length} files`;
19493
+ if (!additions && !deletions)
19494
+ return fileLabel;
19495
+ if (!deletions)
19496
+ return `${fileLabel} \xB7 +${additions}`;
19497
+ if (!additions)
19498
+ return `${fileLabel} \xB7 \u2212${deletions}`;
19499
+ return `${fileLabel} \xB7 +${additions} \u2212${deletions}`;
19500
+ }
19501
+ function withLanguage(path) {
19502
+ const language = languageFromPath(path);
19503
+ return language ? { language } : {};
19504
+ }
19505
+ function diffFileFromPatch(path, patch, status = "modified") {
19506
+ const stats = countPatchStats(patch);
19507
+ return {
19508
+ path,
19509
+ status,
19510
+ ...withLanguage(path),
19511
+ additions: stats.additions || void 0,
19512
+ deletions: stats.deletions || void 0,
19513
+ ...capPatch(patch)
19514
+ };
19515
+ }
19516
+ function diffFileFromWrite(path, content) {
19517
+ const capped = capPatch(content);
19518
+ return {
19519
+ path,
19520
+ status: "added",
19521
+ ...withLanguage(path),
19522
+ additions: content.split("\n").length,
19523
+ before: "",
19524
+ after: capped.patch,
19525
+ ...capped.truncated ? { truncated: true } : {}
19526
+ };
19527
+ }
19528
+ function splitUnifiedDiff(raw) {
19529
+ const text = raw.replace(/\r\n/g, "\n");
19530
+ const starts = [];
19531
+ const header = /^diff --git /gm;
19532
+ let match;
19533
+ while (match = header.exec(text))
19534
+ starts.push(match.index);
19535
+ if (starts.length === 0) {
19536
+ if (!text.trim())
19537
+ return [];
19538
+ return [diffFileFromPatch("diff", text)];
19539
+ }
19540
+ return starts.map((start, index) => {
19541
+ const chunk = text.slice(start, starts[index + 1]);
19542
+ const names = /^diff --git a\/(.+?) b\/(.+)$/m.exec(chunk);
19543
+ const oldPath = names?.[1] ?? "unknown";
19544
+ const path = names?.[2] ?? oldPath;
19545
+ let status = "modified";
19546
+ if (/^new file mode /m.test(chunk) || oldPath === "/dev/null")
19547
+ status = "added";
19548
+ else if (/^deleted file mode /m.test(chunk) || path === "/dev/null")
19549
+ status = "deleted";
19550
+ else if (/^rename from /m.test(chunk) || oldPath !== path)
19551
+ status = "renamed";
19552
+ const resolvedPath = path === "/dev/null" ? oldPath : path;
19553
+ return {
19554
+ ...diffFileFromPatch(resolvedPath, chunk, status),
19555
+ ...status === "renamed" && oldPath !== path ? { oldPath } : {}
19556
+ };
19557
+ }).slice(0, MAX_DIFF_FILES);
19558
+ }
19559
+ function pathFromArgs(input) {
19560
+ if (!isRecord(input))
19561
+ return void 0;
19562
+ return asString(input.path) ?? asString(input.file_path) ?? asString(input.target_file) ?? asString(input.notebook_path);
19563
+ }
19564
+ function writeContent(input) {
19565
+ if (!isRecord(input))
19566
+ return void 0;
19567
+ if (typeof input.content === "string")
19568
+ return input.content;
19569
+ if (typeof input.contents === "string")
19570
+ return input.contents;
19571
+ if (typeof input.new_source === "string")
19572
+ return input.new_source;
19573
+ return void 0;
19574
+ }
19575
+ function editPatchFromResult(result) {
19576
+ if (!isRecord(result))
19577
+ return void 0;
19578
+ const details = isRecord(result.details) ? result.details : void 0;
19579
+ return asString(details?.patch) ?? asString(result.patch);
19580
+ }
19581
+ function patchFromReplace(input) {
19582
+ if (!isRecord(input))
19583
+ return void 0;
19584
+ const oldText = asString(input.old_string) ?? asString(input.oldText) ?? asString(input.old_str);
19585
+ const newText = asString(input.new_string) ?? asString(input.newText) ?? asString(input.new_str);
19586
+ if (oldText == null || newText == null)
19587
+ return void 0;
19588
+ return `--- a
19589
+ +++ b
19590
+ @@
19591
+ ${oldText.split("\n").map((line) => `-${line}`).join("\n")}
19592
+ ${newText.split("\n").map((line) => `+${line}`).join("\n")}
19593
+ `;
19594
+ }
19595
+ function diffFileFromMutationTool(args) {
19596
+ const path = pathFromArgs(args.input);
19597
+ if (!path)
19598
+ return null;
19599
+ const patch = editPatchFromResult(args.result);
19600
+ if (patch)
19601
+ return diffFileFromPatch(path, patch);
19602
+ const toolName = args.toolName.replace(/[:/]/g, "_");
19603
+ if (WRITE_TOOLS.test(toolName)) {
19604
+ const content = writeContent(args.input);
19605
+ if (content === void 0)
19606
+ return null;
19607
+ return diffFileFromWrite(path, content);
19608
+ }
19609
+ if (EDIT_TOOLS.test(toolName)) {
19610
+ const replacePatch = patchFromReplace(args.input);
19611
+ if (!replacePatch)
19612
+ return null;
19613
+ return diffFileFromPatch(path, replacePatch);
19614
+ }
19615
+ return null;
19616
+ }
19617
+ function buildDiffWidget(args) {
19618
+ const files = args.files.slice(0, MAX_DIFF_FILES);
19619
+ if (files.length === 0)
19620
+ return null;
19621
+ return {
19622
+ kind: "diff",
19623
+ widgetId: args.widgetId,
19624
+ title: args.title ?? "Changes",
19625
+ description: summarizeDiffFiles(files),
19626
+ files,
19627
+ size: "full",
19628
+ display: "expanded"
19629
+ };
19630
+ }
19631
+ function git(cwd, args) {
19632
+ try {
19633
+ const result = spawnSync("git", ["-C", cwd, ...args], {
19634
+ encoding: "utf8",
19635
+ timeout: 15e3,
19636
+ maxBuffer: 8e6,
19637
+ stdio: ["ignore", "pipe", "pipe"]
19638
+ });
19639
+ if (result.status !== 0)
19640
+ return null;
19641
+ return result.stdout ?? "";
19642
+ } catch {
19643
+ return null;
19644
+ }
19645
+ }
19646
+ function snapshotWorkspace(cwd) {
19647
+ if (!cwd)
19648
+ return null;
19649
+ const inside = git(cwd, ["rev-parse", "--is-inside-work-tree"]);
19650
+ if (inside?.trim() !== "true")
19651
+ return null;
19652
+ const stashSha = git(cwd, ["stash", "create"])?.trim() || void 0;
19653
+ const untracked = git(cwd, ["ls-files", "--others", "--exclude-standard"])?.split("\n").map((line) => line.trim()).filter(Boolean) ?? [];
19654
+ return { cwd, stashSha, untracked };
19655
+ }
19656
+ function mergeDiffFiles(existing, extra) {
19657
+ const byPath = new Map(existing.map((file) => [file.path, file]));
19658
+ for (const file of extra)
19659
+ byPath.set(file.path, file);
19660
+ return [...byPath.values()].slice(0, MAX_DIFF_FILES);
19661
+ }
19662
+ function diffFromSnapshot(snapshot) {
19663
+ if (!snapshot)
19664
+ return [];
19665
+ const { cwd, stashSha, untracked: beforeUntracked } = snapshot;
19666
+ const diffRaw = stashSha ? git(cwd, ["diff", stashSha]) : git(cwd, ["diff", "HEAD"]);
19667
+ const files = diffRaw ? splitUnifiedDiff(diffRaw) : [];
19668
+ const afterUntracked = git(cwd, ["ls-files", "--others", "--exclude-standard"])?.split("\n").map((line) => line.trim()).filter(Boolean) ?? [];
19669
+ const beforeSet = new Set(beforeUntracked);
19670
+ const extras = [];
19671
+ for (const path of afterUntracked) {
19672
+ if (beforeSet.has(path))
19673
+ continue;
19674
+ try {
19675
+ extras.push(diffFileFromWrite(path, readFileSync2(join(cwd, path), "utf8")));
19676
+ } catch {
19677
+ extras.push({ path, status: "added", ...withLanguage(path) });
19678
+ }
19679
+ }
19680
+ return mergeDiffFiles(files, extras);
19681
+ }
19682
+ function resolveRunDiffFiles(args) {
19683
+ const fromGit = diffFromSnapshot(args.snapshot ?? null);
19684
+ if (fromGit.length > 0)
19685
+ return fromGit;
19686
+ return [...args.fallback ?? []].slice(0, MAX_DIFF_FILES);
19687
+ }
19688
+
19409
19689
  // credits-auth.ts
19410
19690
  var INTEGRATIONS_TOKEN_HEADER = "x-openbot-integrations-token";
19411
19691
  var CREDITS_API_KEY_PLACEHOLDER = "openbot-credits";
@@ -19774,6 +20054,8 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19774
20054
  const emittedToolCallIds = /* @__PURE__ */ new Set();
19775
20055
  const emittedToolResultIds = /* @__PURE__ */ new Set();
19776
20056
  const toolTitleByUseId = /* @__PURE__ */ new Map();
20057
+ const changedFiles = /* @__PURE__ */ new Map();
20058
+ const snapshot = snapshotWorkspace(workingDir);
19777
20059
  const emitAssistantText = function* (text) {
19778
20060
  if (!text) return;
19779
20061
  if (authMode === "credits") {
@@ -19837,20 +20119,12 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19837
20119
  yield uiWidget({
19838
20120
  agentId: context.state.agentId,
19839
20121
  threadId,
19840
- widget: {
19841
- kind: "message",
20122
+ widget: toolTraceWidget({
19842
20123
  widgetId: toolCallWidgetId(tool.toolUseId),
20124
+ groupId: "claude-code:tools",
19843
20125
  title: toolTitleByUseId.get(tool.toolUseId)?.title ?? "",
19844
- body: formatToolInputBody(tool.input),
19845
- display: "collapsed",
19846
- metadata: {
19847
- type: "claude_tool",
19848
- phase: "call",
19849
- toolName: tool.title,
19850
- toolUseId: tool.toolUseId,
19851
- source: "claude-code"
19852
- }
19853
- }
20126
+ body: formatToolInputBody(tool.input)
20127
+ })
19854
20128
  });
19855
20129
  }
19856
20130
  continue;
@@ -19876,24 +20150,25 @@ var claudeCodeRuntime = (options = {}) => (builder) => {
19876
20150
  yield uiWidget({
19877
20151
  agentId: context.state.agentId,
19878
20152
  threadId,
19879
- widget: {
19880
- kind: "message",
20153
+ widget: toolTraceWidget({
19881
20154
  widgetId: toolCallWidgetId(res.toolUseId),
20155
+ groupId: "claude-code:tools",
19882
20156
  title: toolTitleByUseId.get(res.toolUseId)?.title ?? "",
19883
20157
  body: formatToolResultBody(
19884
20158
  toolTitleByUseId.get(res.toolUseId)?.input,
19885
20159
  body
19886
20160
  ),
19887
- display: "collapsed",
19888
- ...state ? { state } : {},
19889
- metadata: {
19890
- type: "claude_tool",
19891
- phase: "result",
19892
- toolUseId: res.toolUseId,
19893
- source: "claude-code"
19894
- }
19895
- }
20161
+ state
20162
+ })
19896
20163
  });
20164
+ if (!res.isError) {
20165
+ const file = diffFileFromMutationTool({
20166
+ toolName: toolTitleByUseId.get(res.toolUseId)?.title ?? "",
20167
+ input: toolTitleByUseId.get(res.toolUseId)?.input,
20168
+ result: res.content
20169
+ });
20170
+ if (file) changedFiles.set(file.path, file);
20171
+ }
19897
20172
  }
19898
20173
  }
19899
20174
  }
@@ -19943,6 +20218,20 @@ ${details}` : `[claude-code] run ended with error: ${subtype}`
19943
20218
  if (lastSessionId && lastSessionId !== resumeId) {
19944
20219
  await persistSessionId(context.state, storage, lastSessionId);
19945
20220
  }
20221
+ const diff = buildDiffWidget({
20222
+ widgetId: `claude-code-diff:${threadId ?? "run"}:${Date.now()}`,
20223
+ files: resolveRunDiffFiles({
20224
+ snapshot,
20225
+ fallback: changedFiles.values()
20226
+ })
20227
+ });
20228
+ if (diff) {
20229
+ yield uiWidget({
20230
+ agentId: context.state.agentId,
20231
+ threadId,
20232
+ widget: diff
20233
+ });
20234
+ }
19946
20235
  } catch (error) {
19947
20236
  const errorMessage = formatClaudeCodeError(error, launchContext, stderrChunks);
19948
20237
  if (authMode === "credits") {
@@ -20085,7 +20374,7 @@ var claudeCodePlugin = {
20085
20374
  });
20086
20375
  }
20087
20376
  };
20088
- var claude_code_default = definePlugin(claudeCodePlugin);
20377
+ var plugin_claude_code_default = definePlugin(claudeCodePlugin);
20089
20378
  export {
20090
- claude_code_default as default
20379
+ plugin_claude_code_default as default
20091
20380
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meetopenbot/claude-code",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "description": "Claude Code plugin for OpenBot",
6
6
  "main": "./dist/index.js",
@@ -8,22 +8,28 @@
8
8
  "access": "public"
9
9
  },
10
10
  "exports": {
11
- ".": "./dist/index.js"
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ }
12
16
  },
13
17
  "files": [
14
18
  "dist"
15
19
  ],
16
- "scripts": {
17
- "build": "esbuild index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external:melony --external:zod",
18
- "prepublishOnly": "npm run build"
19
- },
20
20
  "dependencies": {
21
21
  "@anthropic-ai/claude-agent-sdk": "^0.2.138",
22
- "@meetopenbot/plugin-sdk": "^0.1.4"
22
+ "@meetopenbot/plugin-sdk": "^0.2.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "^20.10.1",
26
26
  "esbuild": "^0.21.0",
27
27
  "zod": "^4.3.5"
28
+ },
29
+ "types": "./dist/index.d.ts",
30
+ "scripts": {
31
+ "build": "esbuild index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external:melony --external:zod && node ../../scripts/write-plugin-declaration.mjs",
32
+ "dev": "esbuild index.ts --bundle --platform=node --format=esm --outfile=dist/index.js --external:melony --external:zod --watch",
33
+ "typecheck": "tsc --noEmit --allowImportingTsExtensions --module ESNext --moduleResolution Bundler --target ES2022 --skipLibCheck index.ts"
28
34
  }
29
- }
35
+ }