@cortexkit/aft-opencode 0.40.1 → 0.40.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA6MlD;;;;;;;;;;;;;;;;GAgBG;AAQH,QAAA,MAAM,MAAM,EAAE,MAA6D,CAAC;AA+5B5E,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA0MlD;;;;;;;;;;;;;;;;GAgBG;AAQH,QAAA,MAAM,MAAM,EAAE,MAA6D,CAAC;AA+5B5E,eAAe,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -36231,6 +36231,31 @@ function relativeToWorktree(fp, worktree) {
36231
36231
  function formatReadFooter2(agentSpecifiedRange, data) {
36232
36232
  return formatReadFooter(agentSpecifiedRange, data, { rangeHint: "startLine/endLine" });
36233
36233
  }
36234
+ function readAttachments(data) {
36235
+ return Array.isArray(data.attachments) ? data.attachments : [];
36236
+ }
36237
+ function formatAttachmentSize(bytes) {
36238
+ if (typeof bytes !== "number" || !Number.isFinite(bytes) || bytes < 0)
36239
+ return;
36240
+ if (bytes >= 1024 * 1024)
36241
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
36242
+ if (bytes >= 1024)
36243
+ return `${Math.ceil(bytes / 1024)} KB`;
36244
+ return `${bytes} bytes`;
36245
+ }
36246
+ function formatReadAttachmentOutput(attachment) {
36247
+ const mime = typeof attachment.mime === "string" ? attachment.mime : "application/octet-stream";
36248
+ const size = formatAttachmentSize(attachment.bytes);
36249
+ if (attachment.kind === "image" || mime.startsWith("image/")) {
36250
+ const dimensions = typeof attachment.width === "number" && typeof attachment.height === "number" ? `, ${attachment.width}×${attachment.height}` : "";
36251
+ const resized = attachment.resized === true ? ", resized" : "";
36252
+ return `Read image (${mime}${dimensions}${resized}${size ? `, ${size}` : ""}).`;
36253
+ }
36254
+ if (attachment.kind === "pdf" || mime === "application/pdf") {
36255
+ return `Read PDF${size ? ` (${size})` : ""}.`;
36256
+ }
36257
+ return `Read attachment (${mime}${size ? `, ${size}` : ""}).`;
36258
+ }
36234
36259
  function buildUnifiedDiff(fp, before, after) {
36235
36260
  const beforeLines = before.split(`
36236
36261
  `);
@@ -36516,7 +36541,7 @@ Behavior:
36516
36541
  - Lines longer than 2000 characters are truncated
36517
36542
  - Output capped at 50KB
36518
36543
  - Binary files are auto-detected and return a size-only message
36519
- - Image files (.png, .jpg, .gif, .webp, etc.) and PDFs return a metadata string (format, size, path) no file content is returned
36544
+ - Supported images (PNG, JPEG, GIF, WebP) and PDFs are returned as tool attachments; range arguments are ignored for media
36520
36545
  - Directories return sorted entries with trailing / for subdirectories
36521
36546
 
36522
36547
  Examples:
@@ -36556,44 +36581,6 @@ function createReadTool(ctx) {
36556
36581
  return permissionDeniedResponse(error50.message);
36557
36582
  return permissionDeniedResponse("Permission denied.");
36558
36583
  }
36559
- const ext = path5.extname(filePath).toLowerCase();
36560
- const mimeMap = {
36561
- ".png": "image/png",
36562
- ".jpg": "image/jpeg",
36563
- ".jpeg": "image/jpeg",
36564
- ".gif": "image/gif",
36565
- ".webp": "image/webp",
36566
- ".bmp": "image/bmp",
36567
- ".ico": "image/x-icon",
36568
- ".tiff": "image/tiff",
36569
- ".tif": "image/tiff",
36570
- ".avif": "image/avif",
36571
- ".heic": "image/heic",
36572
- ".heif": "image/heif",
36573
- ".pdf": "application/pdf"
36574
- };
36575
- const mime = mimeMap[ext];
36576
- if (mime) {
36577
- const isImage = mime.startsWith("image/");
36578
- const label = isImage ? "Image" : "PDF";
36579
- let fileSize = 0;
36580
- try {
36581
- const stat = await import("node:fs/promises").then((fs6) => fs6.stat(filePath));
36582
- fileSize = stat.size;
36583
- } catch {}
36584
- const sizeStr = fileSize > 1048576 ? `${(fileSize / 1048576).toFixed(1)}MB` : fileSize > 1024 ? `${(fileSize / 1024).toFixed(0)}KB` : `${fileSize} bytes`;
36585
- const msg = `${label} read successfully`;
36586
- return {
36587
- output: `${msg} (${ext.slice(1).toUpperCase()}, ${sizeStr}). File: ${filePath}`,
36588
- title: path5.relative(projectRoot, filePath),
36589
- metadata: {
36590
- preview: msg,
36591
- filepath: filePath,
36592
- isImage,
36593
- isPdf: mime === "application/pdf"
36594
- }
36595
- };
36596
- }
36597
36584
  const rawStartLine = coerceOptionalInt(args.startLine, "startLine", 1, Number.MAX_SAFE_INTEGER);
36598
36585
  const rawEndLine = coerceOptionalInt(args.endLine, "endLine", 1, Number.MAX_SAFE_INTEGER);
36599
36586
  const rawLimit = coerceOptionalInt(args.limit, "limit", 1, Number.MAX_SAFE_INTEGER);
@@ -36618,6 +36605,31 @@ function createReadTool(ctx) {
36618
36605
  throw new Error(data.message || "read failed");
36619
36606
  }
36620
36607
  const dp = relativeToWorktree(filePath, projectRoot) || file2;
36608
+ const attachments = readAttachments(data);
36609
+ if (attachments.length > 0) {
36610
+ const toolAttachments = attachments.filter((attachment) => typeof attachment.mime === "string" && typeof attachment.data === "string").map((attachment) => ({
36611
+ type: "file",
36612
+ mime: attachment.mime,
36613
+ url: `data:${attachment.mime};base64,${attachment.data}`
36614
+ }));
36615
+ if (toolAttachments.length > 0) {
36616
+ const first = attachments[0];
36617
+ const firstMime = typeof first.mime === "string" ? first.mime : "";
36618
+ const output2 = typeof data.content === "string" && data.content.length > 0 ? data.content : formatReadAttachmentOutput(first);
36619
+ return {
36620
+ output: output2,
36621
+ title: dp,
36622
+ attachments: toolAttachments,
36623
+ metadata: {
36624
+ preview: output2,
36625
+ filepath: filePath,
36626
+ title: dp,
36627
+ isImage: first.kind === "image" || firstMime.startsWith("image/"),
36628
+ isPdf: first.kind === "pdf" || firstMime === "application/pdf"
36629
+ }
36630
+ };
36631
+ }
36632
+ }
36621
36633
  if (data.entries) {
36622
36634
  return {
36623
36635
  output: data.entries.join(`
@@ -36797,7 +36809,7 @@ function createEditTool(ctx, writeToolName = "write") {
36797
36809
  execute: async (args, context) => {
36798
36810
  const argsRecord = args;
36799
36811
  if (argsRecord.startLine !== undefined || argsRecord.endLine !== undefined) {
36800
- throw new Error("edit: 'startLine'/'endLine' are not top-level parameters. For line-range edits, nest them inside the `edits` array: `edits: [{ startLine: N, endLine: M, content: \"...\" }]`. For find/replace, use `oldString`/`newString` instead.");
36812
+ throw new Error("edit: 'startLine'/'endLine' are not top-level parameters. " + "For line-range edits, nest them inside the `edits` array: " + '`edits: [{ startLine: N, endLine: M, content: "..." }]`. ' + "For find/replace, use `oldString`/`newString` instead.");
36801
36813
  }
36802
36814
  const file2 = args.filePath;
36803
36815
  if (!file2)
@@ -37332,7 +37344,11 @@ ${fileList}`;
37332
37344
  }
37333
37345
  var DELETE_DESCRIPTION = `Delete one or more files (or directories) with backup.
37334
37346
 
37335
- ` + "Each file is backed up before deletion — use aft_safety undo to recover any of them. " + "For directories, every file inside is individually backed up before the tree is removed.\n\nDirectory deletion requires recursive: true. Without it, passing a directory returns an error.\n\nPartial success is allowed: deletable files are deleted; failed ones are reported in `skipped_files` with `complete: false`.";
37347
+ ` + "Each file is backed up before deletion — use aft_safety undo to recover any of them. " + `For directories, every file inside is individually backed up before the tree is removed.
37348
+
37349
+ ` + `Directory deletion requires recursive: true. Without it, passing a directory returns an error.
37350
+
37351
+ ` + "Partial success is allowed: deletable files are deleted; failed ones are reported in `skipped_files` with `complete: false`.";
37336
37352
  function createDeleteTool(ctx) {
37337
37353
  return {
37338
37354
  description: DELETE_DESCRIPTION,
@@ -37389,7 +37405,8 @@ function createDeleteTool(ctx) {
37389
37405
  }
37390
37406
  };
37391
37407
  }
37392
- var MOVE_DESCRIPTION = "Move or rename a file with backup. Creates parent directories for destination automatically\nNote: This moves/renames files at the OS level. To move a code symbol (function, class, type) between files while updating imports, use `aft_refactor` op='move' instead.";
37408
+ var MOVE_DESCRIPTION = `Move or rename a file with backup. Creates parent directories for destination automatically
37409
+ ` + "Note: This moves/renames files at the OS level. To move a code symbol (function, class, type) between files while updating imports, use `aft_refactor` op='move' instead.";
37393
37410
  function createMoveTool(ctx) {
37394
37411
  return {
37395
37412
  description: MOVE_DESCRIPTION,
@@ -38969,12 +38986,9 @@ var PLUGIN_VERSION = (() => {
38969
38986
  return "0.0.0";
38970
38987
  }
38971
38988
  })();
38972
- var ANNOUNCEMENT_VERSION = "0.40.0";
38989
+ var ANNOUNCEMENT_VERSION = "0.40.3";
38973
38990
  var ANNOUNCEMENT_FEATURES = [
38974
- "Groundwork for Subconscious, the CortexKit daemon: configuration now lives in one place under ~/.config/cortexkit/ and <project>/.cortexkit/ (auto-migrated). The daemon integration is dormant nothing changes in how you run AFT today.",
38975
- "Bash output never hides a failure: piped commands run exactly as written with their real exit status, cancelled tasks report as failed, and a failing run is never compressed to a clean-looking summary.",
38976
- "The top aft_search result is now the complete, ready-to-edit symbol (no re-read needed); test files are hidden from results by default.",
38977
- "format_on_edit is now off by default, and bash commands default to the foreground."
38991
+ "read now hands images (PNG, JPEG, GIF, WebP) to the model as visual attachments instead of a binary placeholder, downsized to stay light in context; on OpenCode, PDFs are handed over too."
38978
38992
  ];
38979
38993
  var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/DSa65w8wuf";
38980
38994
  var plugin = async (input) => initializePluginForDirectory(input);
@@ -1 +1 @@
1
- {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAC;AAItE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkCjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AA8YtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAkKjE;AAsrCD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0B/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAqGnF"}
1
+ {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAC;AAItE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAwEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AA8YtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAqJjE;AAsrCD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0B/E;AAMD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAqGnF"}
package/dist/tui.js CHANGED
@@ -7790,7 +7790,7 @@ var require_src2 = __commonJS((exports, module) => {
7790
7790
  // src/tui/index.tsx
7791
7791
  import { createMemo as createMemo2, createSignal as createSignal2, onCleanup as onCleanup2 } from "solid-js";
7792
7792
  // package.json
7793
- var version = "0.40.1";
7793
+ var version = "0.40.3";
7794
7794
 
7795
7795
  // src/shared/rpc-client.ts
7796
7796
  import { existsSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.40.1",
3
+ "version": "0.40.3",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Agent File Tools (AFT) — tree-sitter and lsp powered code analysis",
6
6
  "main": "dist/index.js",
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@clack/prompts": "^1.2.0",
34
- "@cortexkit/aft-bridge": "0.40.1",
34
+ "@cortexkit/aft-bridge": "0.40.3",
35
35
  "@opentui/core": "^0.4.2",
36
36
  "@opentui/solid": "^0.4.2",
37
37
  "@xterm/headless": "^5.5.0",
@@ -41,12 +41,12 @@
41
41
  "zod": "^4.1.8"
42
42
  },
43
43
  "optionalDependencies": {
44
- "@cortexkit/aft-darwin-arm64": "0.40.1",
45
- "@cortexkit/aft-darwin-x64": "0.40.1",
46
- "@cortexkit/aft-linux-arm64": "0.40.1",
47
- "@cortexkit/aft-linux-x64": "0.40.1",
48
- "@cortexkit/aft-win32-arm64": "0.40.1",
49
- "@cortexkit/aft-win32-x64": "0.40.1"
44
+ "@cortexkit/aft-darwin-arm64": "0.40.3",
45
+ "@cortexkit/aft-darwin-x64": "0.40.3",
46
+ "@cortexkit/aft-linux-arm64": "0.40.3",
47
+ "@cortexkit/aft-linux-x64": "0.40.3",
48
+ "@cortexkit/aft-win32-arm64": "0.40.3",
49
+ "@cortexkit/aft-win32-x64": "0.40.3"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@opencode-ai/plugin": "^1.17.9",