@cortexkit/aft-opencode 0.30.3 → 0.31.1

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":"bg-notifications.d.ts","sourceRoot":"","sources":["../src/bg-notifications.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bg-notifications.d.ts","sourceRoot":"","sources":["../src/bg-notifications.ts"],"names":[],"mappings":"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"}
@@ -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;AAwMlD;;;;;;;;;;;;;;;;;;GAkBG;AAQH,QAAA,MAAM,MAAM,EAAE,MAA6D,CAAC;AAwyB5E,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;AAwMlD;;;;;;;;;;;;;;;;;;GAkBG;AAQH,QAAA,MAAM,MAAM,EAAE,MAA6D,CAAC;AAgzB5E,eAAe,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -12947,7 +12947,7 @@ async function ensureStorageMigrated(opts) {
12947
12947
  import { execFileSync } from "node:child_process";
12948
12948
  import { createHash as createHash2 } from "node:crypto";
12949
12949
  import { chmodSync as chmodSync3, closeSync as closeSync2, copyFileSync as copyFileSync2, createWriteStream as createWriteStream2, existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync5, openSync as openSync2, readdirSync, readFileSync as readFileSync3, readlinkSync, realpathSync, rmSync as rmSync2, statSync as statSync2, symlinkSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
12950
- import { basename, dirname as dirname3, join as join6, relative, resolve } from "node:path";
12950
+ import { basename, dirname as dirname3, isAbsolute, join as join6, relative, resolve, win32 } from "node:path";
12951
12951
  import { Readable as Readable2 } from "node:stream";
12952
12952
  import { pipeline as pipeline2 } from "node:stream/promises";
12953
12953
  var ORT_VERSION = "1.24.4";
@@ -13153,6 +13153,29 @@ function isOnnxVersionCompatible(version) {
13153
13153
  return false;
13154
13154
  return minor >= REQUIRED_ORT_MIN_MINOR;
13155
13155
  }
13156
+ function pathEnvValue() {
13157
+ return process.env.PATH ?? process.env.Path ?? process.env.path ?? "";
13158
+ }
13159
+ function pathEntriesForPlatform() {
13160
+ const delimiter = process.platform === "win32" ? ";" : ":";
13161
+ return pathEnvValue().split(delimiter).map((entry) => entry.trim().replace(/^"|"$/g, "")).filter((entry) => {
13162
+ if (!entry || entry === "." || entry.includes("\x00"))
13163
+ return false;
13164
+ return isAbsolute(entry) || win32.isAbsolute(entry);
13165
+ });
13166
+ }
13167
+ function directoryContainsLibrary(dir, libName) {
13168
+ try {
13169
+ const entries = readdirSync(dir);
13170
+ if (process.platform === "win32") {
13171
+ const expected = libName.toLowerCase();
13172
+ return entries.some((entry) => entry.toLowerCase() === expected);
13173
+ }
13174
+ return entries.includes(libName);
13175
+ } catch {
13176
+ return false;
13177
+ }
13178
+ }
13156
13179
  function findSystemOnnxRuntime(libName) {
13157
13180
  if (!libName)
13158
13181
  return null;
@@ -13161,9 +13184,15 @@ function findSystemOnnxRuntime(libName) {
13161
13184
  searchPaths.push("/opt/homebrew/lib", "/usr/local/lib");
13162
13185
  } else if (process.platform === "linux") {
13163
13186
  searchPaths.push("/usr/lib", "/usr/lib/x86_64-linux-gnu", "/usr/lib/aarch64-linux-gnu", "/usr/local/lib");
13187
+ } else if (process.platform === "win32") {
13188
+ searchPaths.push(...pathEntriesForPlatform());
13164
13189
  }
13190
+ const seen = new Set;
13165
13191
  for (const dir of searchPaths) {
13166
- if (!existsSync5(join6(dir, libName)))
13192
+ if (seen.has(dir))
13193
+ continue;
13194
+ seen.add(dir);
13195
+ if (!directoryContainsLibrary(dir, libName))
13167
13196
  continue;
13168
13197
  const version = detectOnnxVersion(dir, libName);
13169
13198
  if (version && !isOnnxVersionCompatible(version)) {
@@ -13720,6 +13749,36 @@ function formatZoomText(targetLabel, response) {
13720
13749
  return out.join(`
13721
13750
  `);
13722
13751
  }
13752
+ function formatZoomMultiTargetResult(entries) {
13753
+ const rendered = entries.map((entry) => {
13754
+ const { targetLabel, name, response } = entry;
13755
+ if (response.success === false) {
13756
+ const message = typeof response.message === "string" && response.message.length > 0 ? response.message : "zoom failed";
13757
+ return { targetLabel, name, success: false, error: message };
13758
+ }
13759
+ return {
13760
+ targetLabel,
13761
+ name,
13762
+ success: true,
13763
+ content: formatZoomText(targetLabel, response)
13764
+ };
13765
+ });
13766
+ const complete = rendered.every((entry) => entry.success);
13767
+ const sections = [];
13768
+ if (!complete) {
13769
+ sections.push("Incomplete zoom results: one or more symbols failed.");
13770
+ }
13771
+ for (const entry of rendered) {
13772
+ if (entry.success) {
13773
+ sections.push(entry.content ?? "");
13774
+ } else {
13775
+ sections.push(`Symbol "${entry.name}" not found in ${entry.targetLabel}: ${entry.error ?? "zoom failed"}`);
13776
+ }
13777
+ }
13778
+ return { complete, entries: rendered, text: sections.join(`
13779
+
13780
+ `) };
13781
+ }
13723
13782
  // src/bg-notifications.ts
13724
13783
  import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
13725
13784
 
@@ -13781,6 +13840,9 @@ function write(level, message, data, sessionId) {
13781
13840
  function log2(message, data) {
13782
13841
  write("INFO", message, data);
13783
13842
  }
13843
+ function debug(message, data) {
13844
+ write("DEBUG", message, data);
13845
+ }
13784
13846
  function warn2(message, data) {
13785
13847
  write("WARN", message, data);
13786
13848
  }
@@ -13790,6 +13852,9 @@ function error2(message, data) {
13790
13852
  function sessionLog(sessionId, message, data) {
13791
13853
  write("INFO", message, data, sessionId);
13792
13854
  }
13855
+ function sessionDebug(sessionId, message, data) {
13856
+ write("DEBUG", message, data, sessionId);
13857
+ }
13793
13858
  function sessionWarn(sessionId, message, data) {
13794
13859
  write("WARN", message, data, sessionId);
13795
13860
  }
@@ -14249,7 +14314,8 @@ async function triggerWakeIfPending(drainContext, skipDrain, includeDeferredComp
14249
14314
  body
14250
14315
  });
14251
14316
  } catch (err) {
14252
- sessionWarn(drainContext.sessionID, `${LOG_PREFIX} wake promptAsync error`, {
14317
+ const logPromptError = clientPath === "live-server" ? sessionDebug : sessionWarn;
14318
+ logPromptError(drainContext.sessionID, `${LOG_PREFIX} wake promptAsync error`, {
14253
14319
  event: "bash_completion_wake_prompt_async_error",
14254
14320
  delivery_id: deliveryID2,
14255
14321
  attempt: state.wakeRetryAttempts + 1,
@@ -14276,7 +14342,7 @@ async function triggerWakeIfPending(drainContext, skipDrain, includeDeferredComp
14276
14342
  return;
14277
14343
  } catch (err) {
14278
14344
  setLiveServerWakeAvailable(drainContext.serverUrl, false);
14279
- sessionWarn(drainContext.sessionID, `${LOG_PREFIX} live-server wake failed; falling back`, {
14345
+ sessionDebug(drainContext.sessionID, `${LOG_PREFIX} live-server wake failed; falling back`, {
14280
14346
  event: "bash_completion_wake_live_server_fallback",
14281
14347
  task_ids: taskIDs,
14282
14348
  directory: drainContext.directory,
@@ -28859,7 +28925,7 @@ import { basename as basename2, dirname as dirname5, join as join11 } from "node
28859
28925
  var import_comment_json2 = __toESM(require_src2(), 1);
28860
28926
  import { existsSync as existsSync7, readFileSync as readFileSync5, statSync as statSync3, writeFileSync as writeFileSync4 } from "node:fs";
28861
28927
  import { homedir as homedir7 } from "node:os";
28862
- import { dirname as dirname4, isAbsolute, join as join10, resolve as resolve2 } from "node:path";
28928
+ import { dirname as dirname4, isAbsolute as isAbsolute2, join as join10, resolve as resolve2 } from "node:path";
28863
28929
  import { fileURLToPath } from "node:url";
28864
28930
 
28865
28931
  // src/hooks/auto-update-checker/constants.ts
@@ -28954,7 +29020,7 @@ function resolvePathPluginSpec(spec, configPath) {
28954
29020
  return spec.replace(/^file:\/\//, "");
28955
29021
  }
28956
29022
  }
28957
- if (isAbsolute(spec) || /^[A-Za-z]:[\\/]/.test(spec))
29023
+ if (isAbsolute2(spec) || /^[A-Za-z]:[\\/]/.test(spec))
28958
29024
  return spec;
28959
29025
  return resolve2(dirname4(configPath), spec);
28960
29026
  }
@@ -28968,7 +29034,7 @@ function getLocalDevPath(directory) {
28968
29034
  for (const entry of plugins) {
28969
29035
  if (entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))
28970
29036
  continue;
28971
- if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute(entry)) {
29037
+ if (entry.startsWith("file://") || entry.startsWith(".") || isAbsolute2(entry)) {
28972
29038
  const localPath = resolvePathPluginSpec(entry, configPath);
28973
29039
  const pkgPath = findPackageJsonUp(localPath);
28974
29040
  if (!pkgPath)
@@ -32186,6 +32252,7 @@ var optionalInt = (min, max) => z2.number().int().min(min).max(max).optional();
32186
32252
  var LONG_RUNNING_COMMAND_TIMEOUT_MS = {
32187
32253
  callers: 60000,
32188
32254
  trace_to: 60000,
32255
+ trace_to_symbol: 60000,
32189
32256
  trace_data: 60000,
32190
32257
  impact: 60000,
32191
32258
  grep: 60000,
@@ -32195,6 +32262,68 @@ var LONG_RUNNING_COMMAND_TIMEOUT_MS = {
32195
32262
  function timeoutForCommand(command) {
32196
32263
  return LONG_RUNNING_COMMAND_TIMEOUT_MS[command];
32197
32264
  }
32265
+ function asPlainObject(value) {
32266
+ if (!value || typeof value !== "object" || Array.isArray(value))
32267
+ return;
32268
+ return value;
32269
+ }
32270
+ function candidateLocation(candidate) {
32271
+ const file2 = typeof candidate.file === "string" && candidate.file.length > 0 ? candidate.file : undefined;
32272
+ if (!file2)
32273
+ return;
32274
+ const line = typeof candidate.line === "number" && Number.isFinite(candidate.line) ? candidate.line : undefined;
32275
+ return line === undefined ? file2 : `${file2}:${line}`;
32276
+ }
32277
+ function stringifyData(data) {
32278
+ if (data === undefined)
32279
+ return;
32280
+ try {
32281
+ return JSON.stringify(data, null, 2);
32282
+ } catch {
32283
+ return String(data);
32284
+ }
32285
+ }
32286
+ function formatBridgeErrorMessage(command, response, params = {}) {
32287
+ const code = typeof response.code === "string" && response.code.length > 0 ? response.code : undefined;
32288
+ const message = typeof response.message === "string" && response.message.length > 0 ? response.message : `${command} failed`;
32289
+ const data = asPlainObject(response.data);
32290
+ const rawCandidates = Array.isArray(response.candidates) ? response.candidates : Array.isArray(data?.candidates) ? data.candidates : undefined;
32291
+ const rawSymbol = typeof response.symbol === "string" && response.symbol.length > 0 ? response.symbol : typeof data?.symbol === "string" && data.symbol.length > 0 ? data.symbol : undefined;
32292
+ if (code === "ambiguous_target" || code === "target_symbol_not_in_file") {
32293
+ const candidates = (rawCandidates ?? []).map(asPlainObject).filter((candidate) => candidate !== undefined).map(candidateLocation).filter((candidate) => candidate !== undefined);
32294
+ if (candidates.length > 0) {
32295
+ const symbol2 = typeof params.toSymbol === "string" && params.toSymbol.length > 0 ? params.toSymbol : rawSymbol;
32296
+ const target = symbol2 ? `multiple symbols named "${symbol2}"` : message.replace(/[.!?]+$/, "");
32297
+ const action = code === "ambiguous_target" ? "Pass toFile to disambiguate" : "Try one of these files for toFile";
32298
+ return `${command}: ${code} — ${target}. ${action}:
32299
+ ${candidates.map((candidate) => ` - ${candidate}`).join(`
32300
+ `)}`;
32301
+ }
32302
+ }
32303
+ if (!code)
32304
+ return message;
32305
+ const lines = [`${command}: ${code} — ${message}`];
32306
+ const extras = collectStructuredExtras(response);
32307
+ if (extras)
32308
+ lines.push(`data: ${extras}`);
32309
+ return lines.join(`
32310
+ `);
32311
+ }
32312
+ function collectStructuredExtras(response) {
32313
+ const reserved = new Set(["id", "success", "code", "message", "data"]);
32314
+ const extras = {};
32315
+ for (const [key, value] of Object.entries(response)) {
32316
+ if (reserved.has(key))
32317
+ continue;
32318
+ extras[key] = value;
32319
+ }
32320
+ if (Object.keys(extras).length === 0) {
32321
+ return stringifyData(response.data);
32322
+ }
32323
+ if (response.data !== undefined)
32324
+ extras.data = response.data;
32325
+ return stringifyData(extras);
32326
+ }
32198
32327
  function canonicalizeDirectory(dir) {
32199
32328
  const trimmed = dir.replace(/[/\\]+$/, "");
32200
32329
  try {
@@ -32424,9 +32553,7 @@ function astTools(ctx) {
32424
32553
  ` + `IMPORTANT: Patterns must be complete AST nodes (valid code fragments).
32425
32554
  ` + `For functions, include params and body: 'export async function $NAME($$$) { $$$ }' not just 'export async function $NAME'.
32426
32555
 
32427
- ` + `Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python'
32428
-
32429
- ` + "Returns: Text summary — 'Found N match(es) across M file(s)' followed by file:line blocks with matched text and captured meta-variables.",
32556
+ ` + "Examples: pattern='console.log($MSG)' lang='typescript', pattern='async function $NAME($$$) { $$$ }' lang='javascript', pattern='def $FUNC($$$): $$$' lang='python'",
32430
32557
  args: {
32431
32558
  pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
32432
32559
  lang: z3.enum(SUPPORTED_LANGS).describe("Target language"),
@@ -32518,9 +32645,7 @@ ${hint}`;
32518
32645
 
32519
32646
  ` + `Example: pattern='console.log($MSG)' rewrite='logger.info($MSG)' lang='typescript' — replaces all console.log calls with logger.info across TypeScript files.
32520
32647
 
32521
- ` + `**Warning: This tool modifies files directly.** Use dryRun=true to preview. Consider creating an aft_safety checkpoint before bulk replacements.
32522
-
32523
- ` + "Returns: Text summary — 'Replaced N match(es) across M file(s)' (or '[DRY RUN] Would replace...') followed by per-file output. In dry-run mode, each file is shown with its unified diff so you can verify the rewrite before applying (e.g. catch literal $$$ from anonymous-variadic typos). Diff preview is capped at 8KB total; remaining files are summarized.",
32648
+ ` + "**Warning: This tool modifies files directly.** Use dryRun=true to preview (shows per-file unified diff, capped at 8KB). Consider creating an aft_safety checkpoint before bulk replacements.",
32524
32649
  args: {
32525
32650
  pattern: z3.string().describe("AST pattern with meta-variables ($VAR, $$$). Must be complete AST node."),
32526
32651
  rewrite: z3.string().describe("Replacement pattern (can use $VAR from pattern)"),
@@ -33045,7 +33170,7 @@ var FOREGROUND_WAIT_WINDOW_MS = 5000;
33045
33170
  var FOREGROUND_POLL_INTERVAL_MS = 100;
33046
33171
  var BASH_TRANSPORT_TIMEOUT_MS = 30000;
33047
33172
  var DEFAULT_HARD_TIMEOUT_MS = 30 * 60 * 1000;
33048
- var BASH_DESCRIPTION = `Hoisted bash tool with output compression, command rewriting to AFT tools, optional background execution, and PTY mode for interactive programs. By default, output is compressed; pass compressed: false for raw output. Pass background: true to spawn in the background and get a task_id for bash_status/bash_kill. Pass pty: true with background: true for interactive REPLs and drive them with bash_status({ outputMode: "screen" }) plus bash_write. Use bash_watch to block on or register for pattern matches and exit events.`;
33173
+ var BASH_DESCRIPTION = `Hoisted bash tool with output compression, command rewriting to AFT tools, optional background execution, and PTY mode for interactive programs. By default, output is compressed; pass compressed: false for raw output. Pass background: true to spawn in the background and get a taskId for bash_status/bash_kill. Pass pty: true for interactive REPLs and drive them with bash_status({ outputMode: "screen" }) plus bash_write (pty implies background automatically). Use bash_watch to block on or register for pattern matches and exit events.`;
33049
33174
  async function withPermissionLoop(ctx, runtime, params, bridgeCall, options) {
33050
33175
  const first = await bridgeCall(ctx, runtime, "bash", params, options);
33051
33176
  if (first.success !== false || first.code !== "permission_required")
@@ -33076,7 +33201,7 @@ function createBashTool(ctx) {
33076
33201
  timeout: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("Hard kill cap in milliseconds (positive integer). When omitted, the task can run up to 30 minutes. Foreground bash returns inline if the command finishes within ~5s; otherwise it's automatically promoted to background and a completion reminder is delivered when the task actually finishes."),
33077
33202
  workdir: z4.string().optional().describe("Working directory for command execution. Relative paths resolve through the bridge; defaults to the current tool context/project root when omitted."),
33078
33203
  description: z4.string().optional().describe("Short 5-10 word human-readable summary shown in OpenCode UI metadata instead of raw shell syntax."),
33079
- background: z4.boolean().optional().describe("When true, spawn the command in the background and return a task_id for bash_status/bash_kill instead of waiting for completion. Defaults to false."),
33204
+ background: z4.boolean().optional().describe("When true, spawn the command in the background and return a taskId for bash_status/bash_kill instead of waiting for completion. Defaults to false."),
33080
33205
  compressed: z4.boolean().optional().describe("When true or omitted, return compressed output with noisy terminal control sequences reduced. Set to false for raw output."),
33081
33206
  pty: z4.boolean().optional().describe('When true, spawn the command in a real PTY for interactive programs (python/node/bash REPLs, vim). Implies background: true automatically. Unavailable in subagent sessions. Inspect with bash_status({ taskId, outputMode: "screen" }) and drive interactively with bash_write — its input accepts either a string OR an array like [ "iHello", { key: "esc" }, ":wq", { key: "enter" } ] for atomic text+key sequences.'),
33082
33207
  ptyRows: optionalInt(1, 60).describe("PTY terminal height in rows — ignored when pty is false. Defaults to 24 when pty: true. Minimum 1, maximum 60."),
@@ -33230,7 +33355,7 @@ function createBashTool(ctx) {
33230
33355
  }
33231
33356
  function createBashStatusTool(ctx) {
33232
33357
  return {
33233
- description: "Read-only snapshot of a background or PTY bash task's current state and output. Returns immediately. Use bash_watch to block on or register for pattern matches and exit events.",
33358
+ description: "Read-only snapshot of a background or PTY bash task's current state and output. Returns immediately. Never waits. Use bash_watch to block on or register for pattern matches and exit events.",
33234
33359
  args: {
33235
33360
  taskId: z4.string().describe("Background task ID returned by bash({ background: true }), e.g. bash-6b454047."),
33236
33361
  outputMode: z4.enum(["screen", "raw", "both"]).optional().describe("PTY output rendering mode. Defaults to screen for PTY tasks and preserves existing behavior for piped tasks when omitted.")
@@ -34224,7 +34349,7 @@ function createEditTool(ctx, writeToolName = "write") {
34224
34349
  replaceAll: z7.boolean().optional().describe("Replace all occurrences"),
34225
34350
  occurrence: optionalInt(0, Number.MAX_SAFE_INTEGER).describe("0-indexed occurrence to replace when multiple matches exist"),
34226
34351
  symbol: z7.string().optional().describe("Named symbol to replace (function, class, type)"),
34227
- content: z7.string().optional().describe("New content for symbol replace or file write"),
34352
+ content: z7.string().optional().describe("Replacement content for symbol mode or operations[].command='write'. For whole-file writes, use the `write` tool."),
34228
34353
  appendContent: z7.string().optional().describe("Text to append to the end of filePath; creates the file if needed"),
34229
34354
  edits: z7.array(z7.record(z7.string(), z7.unknown())).optional().describe("Batch edits — array of { oldString: string, newString: string } or { startLine: number (1-based), endLine: number (1-based, inclusive), content: string }"),
34230
34355
  operations: z7.array(z7.record(z7.string(), z7.unknown())).optional().describe("Transaction — array of { file: string, command: 'edit_match' | 'write', match?: string, replacement?: string, content?: string } for multi-file edits with rollback. Note: uses 'file'/'match'/'replacement' (not filePath/oldString/newString)")
@@ -34428,7 +34553,7 @@ Example patch:
34428
34553
  \`\`\`
34429
34554
 
34430
34555
  **Behavior:**
34431
- - All file changes are applied with checkpoint-based rollback if any file fails, previous changes are rolled back (best-effort)
34556
+ - Per-file commit: each file's edits apply independently. If a later file fails, earlier successful changes are kept. A pre-patch checkpoint is created automatically — use \`aft_safety\` undo if you need to revert.
34432
34557
  - Files are backed up before modification
34433
34558
  - Parent directories are created automatically for new files
34434
34559
  - Fuzzy matching for context anchors (handles whitespace and Unicode differences)
@@ -34710,11 +34835,7 @@ ${fileList}`;
34710
34835
  }
34711
34836
  var DELETE_DESCRIPTION = `Delete one or more files (or directories) with backup.
34712
34837
 
34713
- ` + "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.
34714
-
34715
- Directory deletion requires recursive: true. Without it, passing a directory returns an error.
34716
-
34717
- Returns: { success, complete, deleted: [paths], skipped_files: [{file, reason}] }. Partial success is allowed: files that can be deleted are deleted; files that fail (missing, permission denied, etc.) are reported in skipped_files. \`complete: false\` indicates at least one file was skipped.`;
34838
+ ` + "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`.";
34718
34839
  function createDeleteTool(ctx) {
34719
34840
  return {
34720
34841
  description: DELETE_DESCRIPTION,
@@ -34767,14 +34888,13 @@ function createDeleteTool(ctx) {
34767
34888
  }
34768
34889
  };
34769
34890
  }
34770
- var MOVE_DESCRIPTION = `Move or rename a file with backup. Creates parent directories for destination automatically
34771
- Note: This moves/renames files at the OS level.`;
34891
+ 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.";
34772
34892
  function createMoveTool(ctx) {
34773
34893
  return {
34774
34894
  description: MOVE_DESCRIPTION,
34775
34895
  args: {
34776
- filePath: z7.string().describe("Source file path to move"),
34777
- destination: z7.string().describe("Destination file path")
34896
+ filePath: z7.string().describe("Source file path to move (absolute or relative to project root)"),
34897
+ destination: z7.string().describe("Destination file path (absolute or relative to project root)")
34778
34898
  },
34779
34899
  execute: async (args, context) => {
34780
34900
  const filePath = path4.isAbsolute(args.filePath) ? args.filePath : path4.resolve(context.directory, args.filePath);
@@ -34894,12 +35014,7 @@ function importTools(ctx) {
34894
35014
  ` + `Ops:
34895
35015
  ` + `- 'add': Add an import. Auto-detects group (stdlib/external/internal), deduplicates. Requires 'module'. Optional 'names', 'defaultImport', 'typeOnly'.
34896
35016
  ` + `- 'remove': Remove an import or a specific named import. Requires 'module'. Provide 'removeName' to remove a single named import; omit to remove the entire import.
34897
- ` + `- 'organize': Re-sort and re-group all imports by language convention, deduplicate. Requires only 'filePath'. Use aft_safety checkpoint/undo for recovery before broad cleanup.
34898
-
34899
- ` + `Returns:
34900
- ` + `- add: { file, added, module, group?, already_present?, formatted?, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
34901
- ` + `- remove: { file, removed, module, name?, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
34902
- ` + "- organize: { file, groups: [{ name, count }], removed_duplicates, formatted?, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }",
35017
+ ` + "- 'organize': Re-sort and re-group all imports by language convention, deduplicate. Requires only 'filePath'. Use aft_safety checkpoint/undo for recovery before broad cleanup.",
34903
35018
  args: {
34904
35019
  op: z8.enum(["add", "remove", "organize"]).describe("Import operation"),
34905
35020
  filePath: z8.string().describe("Path to the file (absolute or relative to project root)"),
@@ -34957,29 +35072,13 @@ import { tool as tool9 } from "@opencode-ai/plugin";
34957
35072
  var z9 = tool9.schema;
34958
35073
  function lspTools(ctx) {
34959
35074
  const diagnosticsTool = {
34960
- description: "On-demand LSP file/scope check. Spawns the relevant language server (if " + "registered for the file's extension), opens the document, prefers LSP 3.17 " + "pull diagnostics when supported, and falls back to push + waitMs otherwise. " + "NOT a project-wide type checker — for full coverage run `tsc --noEmit`, " + "`cargo check`, `pyright`, etc.\n" + `
34961
- ` + `Returns: {
34962
- ` + ` diagnostics: Array<{file, line, column, end_line, end_column, severity, message, code, source}>,
34963
- ` + ` total: number,
34964
- ` + ` files_with_errors: number,
34965
- ` + ` complete: boolean, // true = trustable absence; false = partial
34966
- ` + ` lsp_servers_used: Array<{ // honest per-server status
34967
- ` + ` server_id, scope: 'file'|'workspace', status: 'pull_ok'|'pull_unchanged'|'push_only'|'no_root_marker (...)' |
34968
- ` + ` 'binary_not_installed: <name>'|'spawn_failed: ...'|'pull_failed: ...'|'workspace_pull_unsupported'|...
34969
- ` + ` }>,
34970
- ` + ` unchecked_files?: string[], // directory mode only — files we have no info for
34971
- ` + ` walk_truncated?: boolean, // directory walk hit the 200-file cap
34972
- ` + ` note?: string // present when no LSP server is registered for the file's extension
34973
- ` + `}
34974
- ` + `
34975
- ` + `**Reading the response honestly:**
34976
- ` + "- `total: 0, complete: true, lsp_servers_used: [{status: 'pull_ok'}]` → file is genuinely clean.\n" + "- `total: 0, lsp_servers_used: []` → **nothing was checked** (no server registered for this extension). Tell the user, don't claim 'no errors'.\n" + "- `lsp_servers_used: [{status: 'binary_not_installed: <name>'}]` → server matched the extension but its binary isn't on PATH. Tell the user to install it.\n" + "- `lsp_servers_used: [{status: 'no_root_marker (...)'}]` → server is registered but couldn't find a workspace root marker walking up from this file. The user's project layout doesn't match what the server expects.\n" + "- `complete: false` (directory mode) → some files in the directory weren't checked; see `unchecked_files`.\n" + `
34977
- ` + "**When this tool gives an unhelpful answer**, run `npx @cortexkit/aft doctor lsp <filePath>` from a terminal to get a full per-server breakdown (registered servers, binary resolution, root-marker resolution, spawn outcome).",
35075
+ description: "On-demand LSP file/scope check. NOT a project-wide type checker — use `tsc --noEmit`, `cargo check`, `pyright` etc. for full coverage.\n" + `
35076
+ ` + "Honesty: `total: 0` is only clean when `complete: true` AND `lsp_servers_used[].status` includes `pull_ok`. Empty `lsp_servers_used`, or any `binary_not_installed`/`spawn_failed`/`no_root_marker`/`push_only` without diagnostics means the file wasn't actually checked — say so, don't report 'clean'. For per-server breakdown run `npx @cortexkit/aft doctor lsp <filePath>`.",
34978
35077
  args: {
34979
35078
  filePath: z9.string().optional().describe("Path to a file to check. Mutually exclusive with 'directory'. Omit both to dump all cached diagnostics."),
34980
- directory: z9.string().optional().describe("Path to a directory. Returns cached diagnostics + workspace pull from active servers; lists files we have no info for in 'unchecked_files'. Capped at 200 walked files."),
35079
+ directory: z9.string().optional().describe("Path to a directory. Returns cached diagnostics + workspace pull; capped at 200 walked files."),
34981
35080
  severity: z9.enum(["error", "warning", "information", "hint", "all"]).optional().describe("Filter by severity (default: 'all')."),
34982
- waitMs: optionalInt(1, 1e4).describe("Wait up to N ms (max 10000, default 0) for push diagnostics to arrive. Only matters for servers that don't support LSP 3.17 pull (bash-language-server, yaml-language-server). Use after an edit to let the server re-analyze.")
35081
+ waitMs: optionalInt(1, 1e4).describe("Wait up to N ms (max 10000) for push diagnostics. Push-only servers like bash-language-server and yaml-language-server use after an edit.")
34983
35082
  },
34984
35083
  execute: async (args, context) => {
34985
35084
  const filePath = args.filePath || undefined;
@@ -35021,18 +35120,21 @@ function navigationTools(ctx) {
35021
35120
  ` + `- 'call_tree': See what a function calls (forward traversal). Use to understand dependencies before modifying a function.
35022
35121
  ` + `- 'callers': Find all call sites of a symbol. Use before renaming or changing a function's signature.
35023
35122
  ` + `- 'trace_to': Trace how execution reaches a function from entry points (routes, exports, main). Use to understand context around deeply-nested code.
35123
+ ` + `- 'trace_to_symbol': Find the shortest call path from one symbol to another symbol across the codebase. Requires 'toSymbol'. If multiple targets match, the error returns candidate files; retry with 'toFile' to disambiguate.
35024
35124
  ` + `- 'impact': Analyze what breaks if a symbol changes. Returns affected callers with signatures and entry point status.
35025
35125
  ` + `- 'trace_data': Follow a value through variable assignments and function parameters across files. Requires 'symbol' (scope to trace from) and 'expression'.
35026
35126
 
35027
- ` + `All ops require both 'filePath' and 'symbol'. The 'expression' parameter is additionally required for trace_data.
35127
+ ` + `All ops require both 'filePath' and 'symbol'. The 'expression' parameter is additionally required for trace_data; 'toSymbol' is additionally required for trace_to_symbol.
35028
35128
 
35029
35129
  `,
35030
35130
  args: {
35031
- op: z10.enum(["call_tree", "callers", "trace_to", "impact", "trace_data"]).describe("Navigation operation"),
35131
+ op: z10.enum(["call_tree", "callers", "trace_to", "trace_to_symbol", "impact", "trace_data"]).describe("Navigation operation"),
35032
35132
  filePath: z10.string().describe("Path to the source file containing the symbol (absolute or relative to project root)"),
35033
35133
  symbol: z10.string().describe("Name of the symbol to analyze"),
35034
- depth: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("Max traversal depth (default: call_tree=5, callers=1, trace_to=10, impact=5, trace_data=5)"),
35035
- expression: z10.string().optional().describe("Expression to track through data flow (required for trace_data op)")
35134
+ depth: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("Max traversal depth (default: call_tree=5, callers=1, trace_to=10, trace_to_symbol=10 capped at 16, impact=5, trace_data=5)"),
35135
+ expression: z10.string().optional().describe("Expression to track through data flow (required for trace_data op)"),
35136
+ toSymbol: z10.string().optional().describe("Target symbol name for trace_to_symbol; the returned path ends at this symbol"),
35137
+ toFile: z10.string().optional().describe("Optional target file for trace_to_symbol; required when toSymbol exists in multiple files")
35036
35138
  },
35037
35139
  execute: async (args, context) => {
35038
35140
  const params = {
@@ -35043,12 +35145,19 @@ function navigationTools(ctx) {
35043
35145
  params.depth = Number(args.depth);
35044
35146
  if (args.expression !== undefined)
35045
35147
  params.expression = args.expression;
35148
+ if (args.toSymbol !== undefined)
35149
+ params.toSymbol = args.toSymbol;
35150
+ if (args.toFile !== undefined)
35151
+ params.toFile = args.toFile;
35046
35152
  if (args.op === "trace_data" && typeof args.expression !== "string") {
35047
35153
  throw new Error("'expression' is required for 'trace_data' op");
35048
35154
  }
35155
+ if (args.op === "trace_to_symbol" && typeof args.toSymbol !== "string") {
35156
+ throw new Error("'toSymbol' is required for 'trace_to_symbol' op");
35157
+ }
35049
35158
  const response = await callBridge(ctx, context, args.op, params);
35050
35159
  if (response.success === false) {
35051
- throw new Error(response.message || `${args.op} failed`);
35160
+ throw new Error(formatBridgeErrorMessage(args.op, response, params));
35052
35161
  }
35053
35162
  return JSON.stringify(response);
35054
35163
  }
@@ -35057,25 +35166,83 @@ function navigationTools(ctx) {
35057
35166
  }
35058
35167
 
35059
35168
  // src/tools/reading.ts
35060
- import { resolve as resolve8 } from "node:path";
35169
+ import { dirname as dirname11, resolve as resolve8 } from "node:path";
35061
35170
  import { tool as tool11 } from "@opencode-ai/plugin";
35062
35171
  var z11 = tool11.schema;
35172
+ function getCallID3(ctx) {
35173
+ const c = ctx;
35174
+ return c.callID ?? c.callId ?? c.call_id;
35175
+ }
35176
+ function buildZoomTitle(args) {
35177
+ if (args.targets !== undefined && args.targets !== null) {
35178
+ if (Array.isArray(args.targets)) {
35179
+ if (args.targets.length === 1 && args.targets[0]) {
35180
+ return `${args.targets[0].filePath}#${args.targets[0].symbol}`;
35181
+ }
35182
+ return `${args.targets.length} targets across files`;
35183
+ }
35184
+ return `${args.targets.filePath}#${args.targets.symbol}`;
35185
+ }
35186
+ const path5 = args.filePath ?? args.url ?? "";
35187
+ if (typeof args.symbols === "string")
35188
+ return path5 ? `${path5}#${args.symbols}` : args.symbols;
35189
+ if (Array.isArray(args.symbols) && args.symbols.length > 0) {
35190
+ if (args.symbols.length === 1)
35191
+ return path5 ? `${path5}#${args.symbols[0]}` : args.symbols[0];
35192
+ return path5 ? `${path5} (${args.symbols.length} symbols)` : `${args.symbols.length} symbols`;
35193
+ }
35194
+ return path5 || "(no target)";
35195
+ }
35063
35196
  function readingTools(ctx) {
35064
35197
  return {
35065
35198
  aft_outline: {
35066
- description: `Structural outline of source code, documentation files, or remote URLs. For code, returns symbols (functions, classes, types) with line ranges. For Markdown and HTML, returns heading hierarchy. Use this to explore structure before reading specific sections with aft_zoom.
35067
-
35068
- ` + "Pass a single `target`:\n" + ` • file path → outline that file (with signatures)
35199
+ description: "Structural outline of source code, documentation files, or remote URLs. For code, returns symbols (functions, classes, types) with line ranges. For Markdown and HTML, returns heading hierarchy. Use this to explore structure before reading specific sections with aft_zoom. Set `files: true` with a directory target for a flat indexed file tree with language, symbol count, and byte metadata.\n\n" + "Pass a single `target`:\n" + ` • file path → outline that file (with signatures)
35069
35200
  ` + ` • directory path → outline all source files under it (recursively, up to 200 files)
35070
35201
  ` + ` • URL (http:// or https://) → fetch and outline a remote HTML/Markdown document
35071
- ` + " • array of paths → outline multiple files in one call",
35202
+ ` + " • array of paths → outline multiple files in one call; with files:true, every path must be a directory",
35072
35203
  args: {
35073
- target: z11.union([z11.string(), z11.array(z11.string())]).describe("What to outline: a file path, directory path, URL, or array of file paths. The mode is auto-detected: URLs by `http://`/`https://` prefix, directories by stat, arrays as multi-file.")
35204
+ target: z11.union([z11.string(), z11.array(z11.string())]).describe("What to outline: a file path, directory path, URL, or array of paths. The mode is auto-detected: URLs by `http://`/`https://` prefix, directories by stat, arrays as multi-file."),
35205
+ files: z11.boolean().optional().describe("Directory-only mode: when true, target must be a directory or array of directories and the result is a flat file tree with path, language, symbol count, and byte size instead of a symbol outline.")
35074
35206
  },
35075
35207
  execute: async (args, context) => {
35076
35208
  const target = args.target;
35209
+ const filesMode = args.files === true;
35077
35210
  const hasUrl = typeof target === "string" && (target.startsWith("http://") || target.startsWith("https://"));
35078
35211
  const isArray = Array.isArray(target) && target.length > 0;
35212
+ if (filesMode) {
35213
+ if (Array.isArray(target)) {
35214
+ if (target.length === 0) {
35215
+ throw new Error("'target' must be a non-empty string or array of strings");
35216
+ }
35217
+ const permissionDenied2 = await assertOutlineFilesExternalPermissions(context, target);
35218
+ if (permissionDenied2)
35219
+ return permissionDeniedResponse(permissionDenied2);
35220
+ const response3 = await callBridge(ctx, context, "outline", { target, files: true });
35221
+ if (response3.success === false) {
35222
+ throw new Error(response3.message || "outline failed");
35223
+ }
35224
+ return formatOutlineFilesText(response3);
35225
+ }
35226
+ if (typeof target !== "string" || target.length === 0) {
35227
+ throw new Error("'target' must be a non-empty string or array of strings");
35228
+ }
35229
+ const resolvedPath = resolve8(context.directory, target);
35230
+ const permissionDenied = await assertOutlineFilesExternalPermissions(context, resolvedPath);
35231
+ if (permissionDenied)
35232
+ return permissionDeniedResponse(permissionDenied);
35233
+ let isDirectory2 = false;
35234
+ try {
35235
+ const { stat } = await import("node:fs/promises");
35236
+ const st = await stat(resolvedPath);
35237
+ isDirectory2 = st.isDirectory();
35238
+ } catch {}
35239
+ const params = isDirectory2 ? { directory: resolvedPath, files: true } : { file: target, files: true };
35240
+ const response2 = await callBridge(ctx, context, "outline", params);
35241
+ if (response2.success === false) {
35242
+ throw new Error(response2.message || "outline failed");
35243
+ }
35244
+ return formatOutlineFilesText(response2);
35245
+ }
35079
35246
  if (hasUrl) {
35080
35247
  const response2 = await callBridge(ctx, context, "outline", { file: target });
35081
35248
  if (response2.success === false) {
@@ -35118,29 +35285,76 @@ function readingTools(ctx) {
35118
35285
  }
35119
35286
  },
35120
35287
  aft_zoom: {
35121
- description: `Inspect code symbols or documentation sections. For code, returns the full source of a symbol with call-graph annotations (what it calls and what calls it). For Markdown and HTML, returns the section content under the given heading.
35122
-
35123
- Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lookup or 'symbols' for multiple in one call.`,
35288
+ description: "Inspect code symbols or documentation sections. For code, returns the full source of a symbol with call-graph annotations (what it calls and what calls it). For Markdown and HTML, returns the section content under the given heading.\n\nUse exactly ONE mode: `{ filePath, symbols }`, `{ url, symbols }`, or `{ targets }`. `symbols` can be a string or array (one or many lookups in the same file/URL). Use `targets` for cross-file batches: `{ filePath, symbol }` or an array of them.",
35124
35289
  args: {
35125
35290
  filePath: z11.string().optional().describe("Path to file (absolute or relative to project root)"),
35126
35291
  url: z11.string().optional().describe("HTTP/HTTPS URL of an HTML or Markdown document to fetch and zoom into"),
35127
- symbol: z11.string().optional().describe("Symbol name for code, or heading text for Markdown/HTML"),
35128
- symbols: z11.array(z11.string()).optional().describe("Array of symbol names or heading texts for a single batched call"),
35292
+ symbols: z11.union([z11.string(), z11.array(z11.string())]).optional().describe("Symbol name for code, or heading text for Markdown/HTML. Pass a string for one lookup or an array for batched lookups in the same file/URL."),
35293
+ targets: z11.union([
35294
+ z11.object({
35295
+ filePath: z11.string().describe("Path to file (absolute or relative to project root)"),
35296
+ symbol: z11.string().describe("Symbol name in that file")
35297
+ }),
35298
+ z11.array(z11.object({
35299
+ filePath: z11.string().describe("Path to file (absolute or relative to project root)"),
35300
+ symbol: z11.string().describe("Symbol name in that file")
35301
+ }))
35302
+ ]).optional().describe("Cross-file batch: `{ filePath, symbol }` or an array of them. Mutually exclusive with filePath/url/symbols."),
35129
35303
  contextLines: optionalInt(1, Number.MAX_SAFE_INTEGER).describe("Lines of context before/after the symbol (default: 3)")
35130
35304
  },
35131
35305
  execute: async (args, context) => {
35132
35306
  const hasFilePath = typeof args.filePath === "string" && args.filePath.length > 0;
35133
35307
  const hasUrl = typeof args.url === "string" && args.url.length > 0;
35308
+ const hasTargets = args.targets !== undefined && args.targets !== null;
35309
+ const hasSymbols = args.symbols !== undefined && args.symbols !== null && (typeof args.symbols === "string" ? args.symbols.length > 0 : Array.isArray(args.symbols) && args.symbols.length > 0);
35310
+ const zoomCallID = getCallID3(context);
35311
+ if (zoomCallID) {
35312
+ const title = buildZoomTitle(args);
35313
+ storeToolMetadata(context.sessionID, zoomCallID, { title, metadata: { title } });
35314
+ }
35315
+ if (hasTargets) {
35316
+ if (hasFilePath || hasUrl || hasSymbols) {
35317
+ throw new Error("'targets' is mutually exclusive with 'filePath', 'url', and 'symbols'");
35318
+ }
35319
+ const targets = Array.isArray(args.targets) ? args.targets : [args.targets];
35320
+ if (targets.length === 0) {
35321
+ throw new Error("'targets' must be a non-empty object or array");
35322
+ }
35323
+ for (const [i, entry] of targets.entries()) {
35324
+ if (!entry || typeof entry.filePath !== "string" || entry.filePath.length === 0) {
35325
+ throw new Error(`targets[${i}].filePath must be a non-empty string`);
35326
+ }
35327
+ if (typeof entry.symbol !== "string" || entry.symbol.length === 0) {
35328
+ throw new Error(`targets[${i}].symbol must be a non-empty string`);
35329
+ }
35330
+ }
35331
+ const responses = await Promise.all(targets.map((t) => {
35332
+ const params2 = { file: t.filePath, symbol: t.symbol };
35333
+ if (args.contextLines !== undefined)
35334
+ params2.context_lines = args.contextLines;
35335
+ return callBridge(ctx, context, "zoom", params2).catch((err) => ({
35336
+ success: false,
35337
+ message: err instanceof Error ? err.message : String(err)
35338
+ }));
35339
+ }));
35340
+ const entries = targets.map((t, i) => ({
35341
+ targetLabel: t.filePath,
35342
+ name: t.symbol,
35343
+ response: responses[i] ?? { success: false, message: "missing zoom response" }
35344
+ }));
35345
+ return formatZoomMultiTargetResult(entries).text;
35346
+ }
35134
35347
  if (!hasFilePath && !hasUrl) {
35135
- throw new Error("Provide exactly one of 'filePath' or 'url'");
35348
+ throw new Error("Provide exactly one of 'filePath', 'url', or 'targets'");
35136
35349
  }
35137
35350
  if (hasFilePath && hasUrl) {
35138
35351
  throw new Error("Provide exactly ONE of 'filePath' or 'url' — not both");
35139
35352
  }
35140
35353
  const file2 = hasUrl ? args.url : args.filePath;
35141
35354
  const targetLabel = (hasUrl ? args.url : args.filePath) ?? file2;
35142
- if (Array.isArray(args.symbols) && args.symbols.length > 0) {
35143
- const results = await Promise.all(args.symbols.map((sym) => {
35355
+ const symbolsArray = hasSymbols ? typeof args.symbols === "string" ? [args.symbols] : args.symbols : undefined;
35356
+ if (symbolsArray) {
35357
+ const results = await Promise.all(symbolsArray.map((sym) => {
35144
35358
  const params2 = { file: file2, symbol: sym };
35145
35359
  if (args.contextLines !== undefined)
35146
35360
  params2.context_lines = args.contextLines;
@@ -35149,11 +35363,16 @@ Provide exactly ONE of 'filePath' or 'url'. Pass either 'symbol' for a single lo
35149
35363
  message: err instanceof Error ? err.message : String(err)
35150
35364
  }));
35151
35365
  }));
35152
- return formatZoomBatchResult(targetLabel, args.symbols, results).text;
35366
+ if (symbolsArray.length === 1) {
35367
+ const response = results[0] ?? { success: false, message: "missing zoom response" };
35368
+ if (response.success === false) {
35369
+ throw new Error(response.message || "zoom failed");
35370
+ }
35371
+ return formatZoomText(targetLabel, response);
35372
+ }
35373
+ return formatZoomBatchResult(targetLabel, symbolsArray, results).text;
35153
35374
  }
35154
35375
  const params = { file: file2 };
35155
- if (typeof args.symbol === "string")
35156
- params.symbol = args.symbol;
35157
35376
  if (args.contextLines !== undefined)
35158
35377
  params.context_lines = args.contextLines;
35159
35378
  const data = await callBridge(ctx, context, "zoom", params);
@@ -35190,6 +35409,24 @@ function formatZoomBatchResult(targetLabel, symbols, responses) {
35190
35409
 
35191
35410
  `) };
35192
35411
  }
35412
+ var MAX_UNCHECKED_FILES_IN_FOOTER = 10;
35413
+ async function assertOutlineFilesExternalPermissions(context, target) {
35414
+ const targets = Array.isArray(target) ? target : [target];
35415
+ const checkedParents = new Set;
35416
+ for (const rawTarget of targets) {
35417
+ if (typeof rawTarget !== "string" || rawTarget.length === 0)
35418
+ continue;
35419
+ const resolvedPath = resolve8(context.directory, rawTarget);
35420
+ const parentDir = dirname11(resolvedPath);
35421
+ if (checkedParents.has(parentDir))
35422
+ continue;
35423
+ checkedParents.add(parentDir);
35424
+ const denial = await assertExternalDirectoryPermission(context, resolvedPath);
35425
+ if (denial)
35426
+ return denial;
35427
+ }
35428
+ return;
35429
+ }
35193
35430
  function formatOutlineText(response) {
35194
35431
  const text = response.text ?? "";
35195
35432
  const skipped = response.skipped_files;
@@ -35204,6 +35441,36 @@ function formatOutlineText(response) {
35204
35441
  return `${header}Skipped ${skipped.length} file(s):
35205
35442
  ${lines}`;
35206
35443
  }
35444
+ function formatOutlineFilesText(response) {
35445
+ const text = formatOutlineText(response);
35446
+ const uncheckedFiles = Array.isArray(response.unchecked_files) ? response.unchecked_files.filter((file2) => typeof file2 === "string" && file2.length > 0) : [];
35447
+ const isPartial = response.complete === false || response.walk_truncated === true || uncheckedFiles.length > 0;
35448
+ if (!isPartial) {
35449
+ return text;
35450
+ }
35451
+ const footer = [];
35452
+ if (response.walk_truncated === true) {
35453
+ const uncheckedCount = uncheckedFiles.length;
35454
+ const suffix = uncheckedCount > 0 ? ` ${uncheckedCount} additional files in this directory were not indexed.` : " Some files in this directory were not indexed.";
35455
+ footer.push(`⚠ Partial result: walk truncated at 200 files.${suffix}`);
35456
+ } else {
35457
+ const suffix = uncheckedFiles.length > 0 ? ` ${uncheckedFiles.length} files in this directory were not indexed.` : " Some files in this directory were not indexed.";
35458
+ footer.push(`⚠ Partial result:${suffix}`);
35459
+ }
35460
+ if (uncheckedFiles.length > 0) {
35461
+ footer.push("Unchecked files:");
35462
+ footer.push(...uncheckedFiles.slice(0, MAX_UNCHECKED_FILES_IN_FOOTER).map((file2) => ` ${file2}`));
35463
+ const remaining = uncheckedFiles.length - MAX_UNCHECKED_FILES_IN_FOOTER;
35464
+ if (remaining > 0) {
35465
+ footer.push(` ... +${remaining} more`);
35466
+ }
35467
+ }
35468
+ const header = text.length > 0 ? `${text}
35469
+
35470
+ ` : "";
35471
+ return `${header}${footer.join(`
35472
+ `)}`;
35473
+ }
35207
35474
 
35208
35475
  // src/tools/refactoring.ts
35209
35476
  import { tool as tool12 } from "@opencode-ai/plugin";
@@ -35279,9 +35546,7 @@ function refactoringTools(ctx) {
35279
35546
 
35280
35547
  ` + `Each op requires specific parameters — see parameter descriptions for requirements.
35281
35548
 
35282
- ` + `All ops need 'filePath'. Use aft_safety checkpoint/undo before risky refactors.
35283
-
35284
- ` + "Returns: move { ok, files_modified, consumers_updated, checkpoint_name, results }. extract returns { file, name, parameters, return_type, syntax_valid, formatted, ... }. inline returns { file, symbol, call_context, substitutions, conflicts, syntax_valid, formatted, ... }.",
35549
+ ` + "All ops need 'filePath'. Use aft_safety checkpoint/undo before risky refactors.",
35285
35550
  args: {
35286
35551
  op: z12.enum(["move", "extract", "inline"]).describe("Refactoring operation"),
35287
35552
  filePath: z12.string().describe("Path to the source file (absolute or relative to project root)"),
@@ -35390,9 +35655,7 @@ function safetyTools(ctx) {
35390
35655
 
35391
35656
  ` + `Each op requires specific parameters — see parameter descriptions for requirements.
35392
35657
 
35393
- ` + `Use checkpoint before risky multi-file changes. Use undo for quick single-file rollback.
35394
-
35395
- ` + "Returns: undo { path, backup_id }. history { file, entries }. checkpoint { ok, name }. restore { ok, name }. list { checkpoints }.",
35658
+ ` + "Use checkpoint before risky multi-file changes. Use undo for quick single-file rollback.",
35396
35659
  args: {
35397
35660
  op: z13.enum(["undo", "history", "checkpoint", "restore", "list"]).describe("Safety operation"),
35398
35661
  filePath: z13.string().optional().describe("File path (required for history, optional for undo). Absolute or relative to project root"),
@@ -35474,7 +35737,18 @@ function safetyTools(ctx) {
35474
35737
 
35475
35738
  // src/tools/search.ts
35476
35739
  import * as fs7 from "node:fs";
35740
+ import * as os2 from "node:os";
35477
35741
  import * as path6 from "node:path";
35742
+ function expandTilde(input) {
35743
+ if (!input || !input.startsWith("~"))
35744
+ return input;
35745
+ if (input === "~")
35746
+ return os2.homedir();
35747
+ if (input.startsWith("~/") || input.startsWith(`~${path6.sep}`)) {
35748
+ return path6.resolve(os2.homedir(), input.slice(2));
35749
+ }
35750
+ return input;
35751
+ }
35478
35752
  function arg(schema) {
35479
35753
  return schema;
35480
35754
  }
@@ -35506,7 +35780,8 @@ function normalizeGlob(pattern) {
35506
35780
  return pattern;
35507
35781
  }
35508
35782
  function absoluteSearchPath(context, target) {
35509
- return path6.isAbsolute(target) ? target : path6.resolve(context.directory, target);
35783
+ const expanded = expandTilde(target);
35784
+ return path6.isAbsolute(expanded) ? expanded : path6.resolve(context.directory, expanded);
35510
35785
  }
35511
35786
  function searchPathExists(context, target) {
35512
35787
  return fs7.existsSync(absoluteSearchPath(context, target));
@@ -35570,16 +35845,16 @@ function splitIncludeArg(raw) {
35570
35845
  }
35571
35846
  function searchTools(ctx) {
35572
35847
  const grepTool = {
35573
- description: "Search file contents using regular expressions. Returns matching lines with file paths, line numbers, and context.",
35848
+ description: "Search file contents using regular expressions. Returns matching lines with file paths and line numbers (no surrounding context lines — use `read` for that). Always case-sensitive. Capped at 100 matches; if you hit the cap, narrow with `path` or `include` and re-run.",
35574
35849
  args: {
35575
35850
  pattern: arg(exports_external.string().describe("Regular expression pattern to search for")),
35576
35851
  include: arg(exports_external.string().optional().describe("File pattern to include (e.g. '*.ts', '*.{ts,tsx}')")),
35577
- path: arg(exports_external.string().optional().describe("Directory to search in, relative to project root"))
35852
+ path: arg(exports_external.string().optional().describe("Directory to search (absolute or relative to project root)"))
35578
35853
  },
35579
35854
  execute: async (args, context) => {
35580
35855
  const pattern = String(args.pattern);
35581
35856
  const includeArg = args.include ? String(args.include) : undefined;
35582
- const pathArg = args.path ? String(args.path) : undefined;
35857
+ const pathArg = args.path ? expandTilde(String(args.path)) : undefined;
35583
35858
  const grepDenied = await askGrepPermission(context, pattern, {
35584
35859
  path: pathArg,
35585
35860
  include: includeArg
@@ -35612,11 +35887,11 @@ function searchTools(ctx) {
35612
35887
  description: "Find files matching a glob pattern. Returns matching file paths sorted by modification time.",
35613
35888
  args: {
35614
35889
  pattern: arg(exports_external.string().describe("Glob pattern to match (e.g. '**/*.ts', 'src/**/*.test.*')")),
35615
- path: arg(exports_external.string().optional().describe("Directory to search in, relative to project root"))
35890
+ path: arg(exports_external.string().optional().describe("Directory to search (absolute or relative to project root)"))
35616
35891
  },
35617
35892
  execute: async (args, context) => {
35618
- let globPattern = String(args.pattern);
35619
- let globPath = args.path ? String(args.path) : undefined;
35893
+ let globPattern = expandTilde(String(args.pattern));
35894
+ let globPath = args.path ? expandTilde(String(args.path)) : undefined;
35620
35895
  if (!globPath && globPattern.startsWith("/")) {
35621
35896
  const metaIdx = globPattern.search(/[*?{}[\]]/);
35622
35897
  if (metaIdx > 0) {
@@ -35735,14 +36010,7 @@ function structureTools(ctx) {
35735
36010
  ` + `- 'add_decorator': Add Python decorator to function/class. Requires 'target' and 'decorator' (without @). Optional 'position'.
35736
36011
  ` + `- 'add_struct_tags': Add/update Go struct field tags. Requires 'target' (struct name), 'field', 'tag', 'value'.
35737
36012
 
35738
- ` + `Each op requires specific parameters — see parameter descriptions for requirements. Use aft_safety checkpoint/undo before risky transforms.
35739
-
35740
- ` + `Returns:
35741
- ` + `- add_member: { file, scope, position, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
35742
- ` + `- add_derive: { file, target, derives, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
35743
- ` + `- wrap_try_catch: { file, target, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
35744
- ` + `- add_decorator: { file, target, decorator, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }
35745
- ` + "- add_struct_tags: { file, target, field, tag_string, formatted, syntax_valid?, format_skipped_reason?, validation_errors?, validate_skipped_reason?, backup_id?, lsp_diagnostics? }",
36013
+ ` + "Each op requires specific parameters — see parameter descriptions for requirements. Use aft_safety checkpoint/undo before risky transforms.",
35746
36014
  args: {
35747
36015
  op: z15.enum(["add_member", "add_derive", "wrap_try_catch", "add_decorator", "add_struct_tags"]).describe("Transformation operation"),
35748
36016
  filePath: z15.string().describe("Path to the source file (absolute or relative to project root)"),
@@ -35851,7 +36119,7 @@ function buildWorkflowHints(opts) {
35851
36119
  const hasBash = !opts.disabledTools.has(bashName);
35852
36120
  const hasBgBash = hasBash && opts.bashBackgroundEnabled && !opts.disabledTools.has(bashStatusName);
35853
36121
  if (hasOutline && hasZoom) {
35854
- sections.push(`**Web/URL access**: \`aft_outline({ url })\` first for structure, then \`aft_zoom({ url, symbol: "<heading>" })\` for the specific section.`);
36122
+ sections.push(`**Web/URL access**: \`aft_outline({ target: url })\` first for structure, then \`aft_zoom({ url, symbols: "<heading>" })\` for the specific section.`);
35855
36123
  }
35856
36124
  if (hasOutline && hasZoom && (hasGrep || hasSearch)) {
35857
36125
  const locator = hasGrep ? `\`${grepName}\`` : "`aft_search`";
@@ -35863,6 +36131,7 @@ function buildWorkflowHints(opts) {
35863
36131
  "- `callers` — find all call sites before changing a function signature",
35864
36132
  "- `impact` — blast radius (which functions/files will need updates)",
35865
36133
  "- `trace_to` — how execution reaches this code from entry points (routes, exports, main)",
36134
+ "- `trace_to_symbol` — shortest call path from one symbol to another",
35866
36135
  "- `trace_data` — follow a value through assignments and parameters across files"
35867
36136
  ].join(`
35868
36137
  `));
@@ -35975,13 +36244,13 @@ var PLUGIN_VERSION = (() => {
35975
36244
  return "0.0.0";
35976
36245
  }
35977
36246
  })();
35978
- var ANNOUNCEMENT_VERSION = "0.30.0";
36247
+ var ANNOUNCEMENT_VERSION = "0.31.0";
35979
36248
  var ANNOUNCEMENT_FEATURES = [
35980
- 'PTY support for interactive bash. `bash({pty: true, background: true})` spawns commands inside a real terminal runs Python/Node REPLs, vim, htop, less, and nested TUIs. Use `ptyRows`/`ptyCols` (up to 60×140) to size the terminal, `bash_status({outputMode: "screen"})` for the rendered view, and `bash_write` to send keystrokes.',
35981
- "New `bash_watch` tool unifies pattern notifications and sync waits. `bash_watch({taskId, pattern?, timeoutMs?})` blocks inline; `bash_watch({taskId, pattern, background: true})` registers an async watcher that fires `[BG BASH NOTIFY]` on match or task exit and suppresses the default completion reminder.",
35982
- "`bash_status` is now a pure snapshot tool wait and watch semantics moved to `bash_watch`.",
35983
- "URL fetches in `aft_outline` and `aft_zoom` no longer hang indefinitely on slow servers body reads abort with a clear stall error after 15 seconds without data.",
35984
- "Post-restart bg-bash replay is fixed: previously-delivered task completions no longer fire fresh reminders after OpenCode restarts."
36249
+ "`aft_navigate` has a new `trace_to_symbol` op for path-between-symbols queries. One call returns the shortest call path from one function to another with file + line for every hop. Honest errors for ambiguous, missing, or unreachable targets including a candidate list to disambiguate.",
36250
+ '`aft_outline target: "<dir>", files: true` returns an indexed file tree with language, symbol count, and byte size per file. Lets agents pick which files to actually open without first reading symbol bodies. Honest truncation (`complete: false` + `walk_truncated`/`unchecked_files`) when the directory exceeds the walk cap.',
36251
+ '`aft_zoom` adds `targets` for cross-file batchespull bodies from different files in one call. Schema breaking change: `symbol` is removed; pass `symbols: "name"` (string) or `symbols: ["a", "b"]` (array). Same shape works for `url` mode so you can grab multiple sections from one URL fetch.',
36252
+ "Bun/npm/pnpm test compressors now match on output shape, not just on the head token. Wrapper invocations like `bun run --cwd packages/foo test`, `npm test`, and `pnpm test` keep failing-test bodies on the first run instead of dropping them to a generic summary.",
36253
+ "Tool descriptions trimmed: ~1.2K agent-facing tokens removed (-19% on OpenCode, -2% on Pi) by dropping redundant `Returns:` blocks and compressing `lsp_diagnostics` while preserving its load-bearing honesty guidance."
35985
36254
  ];
35986
36255
  var ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU";
35987
36256
  var plugin = async (input) => initializePluginForDirectory(input);
@@ -36172,7 +36441,11 @@ ${lines}
36172
36441
  };
36173
36442
  probeServerReachable(input.serverUrl?.toString()).then((reachable) => {
36174
36443
  setLiveServerWakeAvailable(reachable);
36175
- log2(reachable ? "Live OpenCode HTTP listener reachable; bg-notifications wake path = live-server (anomalyco/opencode#28202 workaround active)." : "Live OpenCode HTTP listener unreachable; bg-notifications wake path = in-process-fallback. Wakes will still arrive but the upstream duplicate-runner bug (anomalyco/opencode#28202) is not worked around. Launch with `opencode --port 0` in TUI mode to activate the workaround.");
36444
+ if (reachable) {
36445
+ log2("Live OpenCode HTTP listener reachable; bg-notifications wake path = live-server (anomalyco/opencode#28202 workaround active).");
36446
+ } else {
36447
+ debug("Live OpenCode HTTP listener unreachable; bg-notifications wake path = in-process-fallback. Wakes will still arrive but the upstream duplicate-runner bug (anomalyco/opencode#28202) is not worked around. Launch with `opencode --port 0` in TUI mode to activate the workaround.");
36448
+ }
36176
36449
  }).catch(() => {
36177
36450
  setLiveServerWakeAvailable(false);
36178
36451
  });
package/dist/logger.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export declare function log(message: string, data?: unknown): void;
2
+ export declare function debug(message: string, data?: unknown): void;
2
3
  export declare function warn(message: string, data?: unknown): void;
3
4
  export declare function error(message: string, data?: unknown): void;
4
5
  /**
@@ -8,6 +9,7 @@ export declare function error(message: string, data?: unknown): void;
8
9
  * project-scoped, not session-scoped — use `log`/`warn`/`error` for those.
9
10
  */
10
11
  export declare function sessionLog(sessionId: string | undefined, message: string, data?: unknown): void;
12
+ export declare function sessionDebug(sessionId: string | undefined, message: string, data?: unknown): void;
11
13
  export declare function sessionWarn(sessionId: string | undefined, message: string, data?: unknown): void;
12
14
  export declare function sessionError(sessionId: string | undefined, message: string, data?: unknown): void;
13
15
  export declare function getLogFilePath(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAuEA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEzD;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE1D;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE/F;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEhG;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEjG;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY;iBACV,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;kBAGpC,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;mBAGpC,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;;CAIrD,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAuEA,wBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEzD;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE3D;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE1D;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAE/F;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEjG;AAED,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEhG;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAEjG;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY;iBACV,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;kBAGpC,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;mBAGpC,MAAM,SAAS;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;;CAIrD,CAAC"}
@@ -67,6 +67,8 @@ export declare function coerceOptionalInt(v: unknown, paramName: string, min: nu
67
67
  export declare const LONG_RUNNING_COMMAND_TIMEOUT_MS: Record<string, number>;
68
68
  /** Returns the per-command timeout override, or undefined to use the bridge default. */
69
69
  export declare function timeoutForCommand(command: string): number | undefined;
70
+ /** Format bridge failure envelopes without dropping structured error data. */
71
+ export declare function formatBridgeErrorMessage(command: string, response: Record<string, unknown>, params?: Record<string, unknown>): string;
70
72
  /**
71
73
  * Minimum shape of the per-tool-call context provided by the OpenCode SDK.
72
74
  *
@@ -1 +1 @@
1
- {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAQhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,GACR,CAAC;AAEhD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,OAAO,EACV,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQlE,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAErE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAW3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY,CAEhF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0BlC;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAE9F"}
1
+ {"version":3,"file":"_shared.d.ts","sourceRoot":"","sources":["../../src/tools/_shared.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAQhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,eAAO,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,GACR,CAAC;AAEhD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,OAAO,EACV,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAWpB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CASlE,CAAC;AAEF,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAErE;AA2BD,8EAA8E;AAC9E,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACnC,MAAM,CAsDR;AAsBD;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAW3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY,CAEhF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACpC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0BlC;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CAE9F"}
@@ -1 +1 @@
1
- {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/tools/ast.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkDjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA4S3E"}
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../src/tools/ast.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAkDjD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0S3E"}
@@ -1 +1 @@
1
- {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAK1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAyEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAkKjE;AAkmCD;;;;;;;;;;;;;;;;GAgBG;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,CA8FnF"}
1
+ {"version":3,"file":"hoisted.d.ts","sourceRoot":"","sources":["../../src/tools/hoisted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAK1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAyEjD,wEAAwE;AACxE,eAAO,MAAM,wBAAwB,GAAI,IAAI,MAAM,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,KAAG,MAChD,CAAC;AAqRtC;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAkKjE;AAwmCD;;;;;;;;;;;;;;;;GAgBG;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,CA8FnF"}
@@ -1 +1 @@
1
- {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/tools/imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAiF9E"}
1
+ {"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../src/tools/imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA6E9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/tools/lsp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA+E3E"}
1
+ {"version":3,"file":"lsp.d.ts","sourceRoot":"","sources":["../../src/tools/lsp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAsD3E"}
@@ -1,7 +1,7 @@
1
1
  import type { ToolDefinition } from "@opencode-ai/plugin";
2
2
  import type { PluginContext } from "../types.js";
3
3
  /**
4
- * Tool definitions for navigation commands: configure, call_tree, callers, trace_to, impact, and trace_data.
4
+ * Tool definitions for navigation commands: configure, call_tree, callers, trace_to, trace_to_symbol, impact, and trace_data.
5
5
  */
6
6
  export declare function navigationTools(ctx: PluginContext): Record<string, ToolDefinition>;
7
7
  //# sourceMappingURL=navigation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/tools/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAkDlF"}
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/tools/navigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAoElF"}
@@ -23,5 +23,6 @@ export declare function readingTools(ctx: PluginContext): Record<string, ToolDef
23
23
  * Exported for regression tests.
24
24
  */
25
25
  export declare function formatZoomBatchResult(targetLabel: string, symbols: string[], responses: Record<string, unknown>[]): ZoomBatchResult;
26
+ export declare function formatOutlineFilesText(response: Record<string, unknown>): string;
26
27
  export {};
27
28
  //# sourceMappingURL=reading.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reading.d.ts","sourceRoot":"","sources":["../../src/tools/reading.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,eAAe;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAmJ/E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GACnC,eAAe,CAyBjB"}
1
+ {"version":3,"file":"reading.d.ts","sourceRoot":"","sources":["../../src/tools/reading.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsCjD,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,eAAe;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAmS/E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GACnC,eAAe,CAyBjB;AA+CD,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CA2ChF"}
@@ -1 +1 @@
1
- {"version":3,"file":"refactoring.d.ts","sourceRoot":"","sources":["../../src/tools/refactoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcjD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA0InF"}
1
+ {"version":3,"file":"refactoring.d.ts","sourceRoot":"","sources":["../../src/tools/refactoring.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAcjD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAyInF"}
@@ -1 +1 @@
1
- {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/tools/safety.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAajD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAsH9E"}
1
+ {"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../../src/tools/safety.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAajD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAqH9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAgHjD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BrD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA6H9E"}
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAiIjD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BrD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAuI9E"}
@@ -1 +1 @@
1
- {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/tools/structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAkKjF"}
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/tools/structure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CA4JjF"}
package/dist/tui.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/tui/index.tsx
2
2
  import { createMemo as createMemo2, createSignal as createSignal2, onCleanup as onCleanup2 } from "solid-js";
3
3
  // package.json
4
- var version = "0.30.3";
4
+ var version = "0.31.1";
5
5
 
6
6
  // src/shared/rpc-client.ts
7
7
  import { existsSync, readdirSync, readFileSync, unlinkSync } from "node:fs";
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,WAAW,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4DAA4D;IAC5D,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAuEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAQjG"}
1
+ {"version":3,"file":"workflow-hints.d.ts","sourceRoot":"","sources":["../src/workflow-hints.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,SAAS,EAAqB,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,WAAW,EAAE,SAAS,GAAG,aAAa,GAAG,KAAK,CAAC;IAC/C,4EAA4E;IAC5E,aAAa,EAAE,OAAO,CAAC;IACvB,mEAAmE;IACnE,eAAe,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,4DAA4D;IAC5D,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAwEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAQjG"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/aft-opencode",
3
- "version": "0.30.3",
3
+ "version": "0.31.1",
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",
@@ -29,7 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@clack/prompts": "^1.2.0",
32
- "@cortexkit/aft-bridge": "0.30.3",
32
+ "@cortexkit/aft-bridge": "0.31.1",
33
33
  "@opencode-ai/plugin": "^1.15.5",
34
34
  "@opencode-ai/sdk": "^1.15.5",
35
35
  "@xterm/headless": "^5.5.0",
@@ -38,12 +38,12 @@
38
38
  "zod": "^4.1.8"
39
39
  },
40
40
  "optionalDependencies": {
41
- "@cortexkit/aft-darwin-arm64": "0.30.3",
42
- "@cortexkit/aft-darwin-x64": "0.30.3",
43
- "@cortexkit/aft-linux-arm64": "0.30.3",
44
- "@cortexkit/aft-linux-x64": "0.30.3",
45
- "@cortexkit/aft-win32-arm64": "0.30.3",
46
- "@cortexkit/aft-win32-x64": "0.30.3"
41
+ "@cortexkit/aft-darwin-arm64": "0.31.1",
42
+ "@cortexkit/aft-darwin-x64": "0.31.1",
43
+ "@cortexkit/aft-linux-arm64": "0.31.1",
44
+ "@cortexkit/aft-linux-x64": "0.31.1",
45
+ "@cortexkit/aft-win32-arm64": "0.31.1",
46
+ "@cortexkit/aft-win32-x64": "0.31.1"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/node": "^22.0.0",
package/src/logger.ts CHANGED
@@ -73,6 +73,10 @@ export function log(message: string, data?: unknown): void {
73
73
  write("INFO", message, data);
74
74
  }
75
75
 
76
+ export function debug(message: string, data?: unknown): void {
77
+ write("DEBUG", message, data);
78
+ }
79
+
76
80
  export function warn(message: string, data?: unknown): void {
77
81
  write("WARN", message, data);
78
82
  }
@@ -91,6 +95,10 @@ export function sessionLog(sessionId: string | undefined, message: string, data?
91
95
  write("INFO", message, data, sessionId);
92
96
  }
93
97
 
98
+ export function sessionDebug(sessionId: string | undefined, message: string, data?: unknown): void {
99
+ write("DEBUG", message, data, sessionId);
100
+ }
101
+
94
102
  export function sessionWarn(sessionId: string | undefined, message: string, data?: unknown): void {
95
103
  write("WARN", message, data, sessionId);
96
104
  }