@cortexkit/aft-opencode 0.37.0 → 0.37.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":"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;AAm5B5E,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;AA8MlD;;;;;;;;;;;;;;;;GAgBG;AAQH,QAAA,MAAM,MAAM,EAAE,MAA6D,CAAC;AAs5B5E,eAAe,MAAM,CAAC"}
package/dist/index.js CHANGED
@@ -14364,14 +14364,27 @@ function isCompressorHandledRunner(stage) {
14364
14364
  if (tokens.some((token) => token === "&&" || token === "||" || token.includes(";"))) {
14365
14365
  return false;
14366
14366
  }
14367
- const first = runnerName(tokens[0]);
14368
- const second = tokens[1];
14369
- const third = tokens[2];
14370
- const rest = tokens.slice(1);
14367
+ let tokenOffset = 0;
14368
+ while (tokenOffset < tokens.length && isEnvAssignment(tokens[tokenOffset])) {
14369
+ tokenOffset++;
14370
+ }
14371
+ const first = runnerName(tokens[tokenOffset]);
14372
+ const runnerArgs = tokens.slice(tokenOffset + 1);
14373
+ const second = runnerArgs[0];
14374
+ const third = runnerArgs[1];
14375
+ const rest = runnerArgs;
14371
14376
  if (!first)
14372
14377
  return false;
14373
- if (first === "bun")
14374
- return second === "test" || second === "run" && startsWithTest(third);
14378
+ if (first === "bun") {
14379
+ let args = rest;
14380
+ if (args[0] === "--cwd")
14381
+ args = args.slice(2);
14382
+ else if (args[0]?.startsWith("--cwd="))
14383
+ args = args.slice(1);
14384
+ const sub = args[0];
14385
+ const subNext = args[1];
14386
+ return sub === "test" || sub === "run" && startsWithTest(subNext);
14387
+ }
14375
14388
  if (first === "npm" || first === "pnpm") {
14376
14389
  return second === "test" || second === "run" && startsWithTest(third);
14377
14390
  }
@@ -14394,14 +14407,20 @@ function isCompressorHandledRunner(stage) {
14394
14407
  return hasBuildTask(rest, ["test", "check", "build", "assemble", "clean"]);
14395
14408
  }
14396
14409
  if (first === "mvn" || first === "mvnw") {
14397
- return hasBuildTask(rest, ["test", "verify", "package", "install"]);
14410
+ return hasBuildTask(rest, ["test", "verify", "package", "install", "clean"]);
14398
14411
  }
14399
14412
  if (first === "dotnet")
14400
14413
  return ["test", "build"].includes(second ?? "");
14401
14414
  if (first === "rspec")
14402
14415
  return true;
14403
- if (first === "rake")
14404
- return second === "test" || second === "spec";
14416
+ if (first === "rake") {
14417
+ const positionals = rest.filter((a) => !a.startsWith("-"));
14418
+ if (positionals.length === 0)
14419
+ return false;
14420
+ if (positionals.some((a) => a.includes("/") || a.includes(".") || a.includes("=")))
14421
+ return false;
14422
+ return positionals.some((a) => a === "test" || a === "spec");
14423
+ }
14405
14424
  if (first === "phpunit" || first === "pest")
14406
14425
  return true;
14407
14426
  if (first === "xcodebuild")
@@ -14424,6 +14443,11 @@ function isCompressorHandledRunner(stage) {
14424
14443
  "nox"
14425
14444
  ].includes(first);
14426
14445
  }
14446
+ function isEnvAssignment(token) {
14447
+ if (!token)
14448
+ return false;
14449
+ return /^[a-zA-Z_][a-zA-Z0-9_]*=/.test(token);
14450
+ }
14427
14451
  function runnerName(token) {
14428
14452
  if (!token)
14429
14453
  return "";
@@ -33751,6 +33775,21 @@ function clearStatusBarSession(sessionID) {
33751
33775
  emitStateBySession.delete(sessionID);
33752
33776
  }
33753
33777
 
33778
+ // src/sync-watch-abort.ts
33779
+ var abortFlags = new Map;
33780
+ function signalSyncWatchAbort(sessionID) {
33781
+ const key = sessionID || "__default__";
33782
+ abortFlags.set(key, true);
33783
+ }
33784
+ function clearSyncWatchAbort(sessionID) {
33785
+ const key = sessionID || "__default__";
33786
+ abortFlags.delete(key);
33787
+ }
33788
+ function isSyncWatchAborted(sessionID) {
33789
+ const key = sessionID || "__default__";
33790
+ return abortFlags.get(key) === true;
33791
+ }
33792
+
33754
33793
  // src/tool-perf.ts
33755
33794
  import { AsyncLocalStorage } from "node:async_hooks";
33756
33795
  var perfStore = new AsyncLocalStorage;
@@ -35219,6 +35258,12 @@ A notification will fire when the pattern matches or the task exits.`;
35219
35258
  const effectiveWaitMs = subagentForcedSync ? MAX_BASH_STATUS_WAIT_TIMEOUT_MS : Math.min(args.timeoutMs ?? DEFAULT_BASH_STATUS_WAIT_TIMEOUT_MS, MAX_BASH_STATUS_WAIT_TIMEOUT_MS);
35220
35259
  const data = await waitForBashStatus(ctx, context, taskId, undefined, waitFor, effectiveWaitMs);
35221
35260
  const waited = data.waited;
35261
+ if (waited?.reason === "user_message") {
35262
+ const convertedText = await convertToAsyncWatchOnAbort(ctx, context, taskId, waitFor, args.once !== false);
35263
+ const metadata2 = context.metadata;
35264
+ metadata2?.({ taskId, status: data.status, waited, convertedToAsync: true });
35265
+ return convertedText;
35266
+ }
35222
35267
  const metadata = context.metadata;
35223
35268
  if (waited)
35224
35269
  metadata?.({ taskId, status: data.status, waited });
@@ -35226,6 +35271,31 @@ A notification will fire when the pattern matches or the task exits.`;
35226
35271
  }
35227
35272
  };
35228
35273
  }
35274
+ async function convertToAsyncWatchOnAbort(ctx, context, taskId, waitFor, once) {
35275
+ if (!waitFor) {
35276
+ return `Sync watch for task ${taskId} was interrupted because you sent a message. ` + `The task is still running in the background. A completion reminder will be ` + `delivered automatically when the task exits; don't poll bash_status.`;
35277
+ }
35278
+ const notifyParams = {
35279
+ task_id: taskId,
35280
+ once
35281
+ };
35282
+ if (waitFor.kind === "regex")
35283
+ notifyParams.regex = waitFor.source;
35284
+ else
35285
+ notifyParams.pattern = waitFor.value;
35286
+ markExplicitControl(context.sessionID, taskId, false);
35287
+ try {
35288
+ const registered = await callBashBridge(ctx, context, "bash_notify", notifyParams);
35289
+ if (registered.success === false) {
35290
+ unmarkExplicitControl(context.sessionID, taskId);
35291
+ return `Sync watch for task ${taskId} was interrupted because you sent a message. ` + `Auto-registering an async watch failed (${String(registered.message ?? "unknown error")}). ` + `The task is still running in the background. A completion reminder will be ` + `delivered automatically when the task exits.`;
35292
+ }
35293
+ return `Sync watch for task ${taskId} was interrupted because you sent a message. ` + `The wait has been converted to an async watch (${registered.watch_id}). ` + `A notification will fire when the pattern matches or the task exits.`;
35294
+ } catch (err) {
35295
+ unmarkExplicitControl(context.sessionID, taskId);
35296
+ return `Sync watch for task ${taskId} was interrupted because you sent a message. ` + `Auto-registering an async watch failed (${err instanceof Error ? err.message : String(err)}). ` + `The task is still running in the background. A completion reminder will be ` + `delivered automatically when the task exits.`;
35297
+ }
35298
+ }
35229
35299
  function formatWatchResultText(taskId, data, waited) {
35230
35300
  const status = data.status;
35231
35301
  const exit = typeof data.exit_code === "number" ? ` (exit ${data.exit_code})` : "";
@@ -35265,6 +35335,7 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
35265
35335
  let scanText = "";
35266
35336
  let scanBaseOffset = 0;
35267
35337
  const bridgeOptions = {};
35338
+ clearSyncWatchAbort(runtime.sessionID);
35268
35339
  markTaskWaiting(runtime.sessionID, taskId);
35269
35340
  let sawTerminal = false;
35270
35341
  try {
@@ -35303,6 +35374,9 @@ async function waitForBashStatus(ctx, runtime, taskId, outputMode, waitFor, effe
35303
35374
  await markBgCompletionDelivered({ ctx, directory: projectRootFor(runtime), sessionID: runtime.sessionID }, taskId);
35304
35375
  return withWaited(data, { reason: "exited", elapsed_ms: Date.now() - startedAt });
35305
35376
  }
35377
+ if (isSyncWatchAborted(runtime.sessionID)) {
35378
+ return withWaited(data, { reason: "user_message", elapsed_ms: Date.now() - startedAt });
35379
+ }
35306
35380
  if (Date.now() >= deadline) {
35307
35381
  return withWaited(data, { reason: "timeout", elapsed_ms: Date.now() - startedAt });
35308
35382
  }
@@ -38463,6 +38537,7 @@ Install: ${getManualInstallHint()}`).catch(() => {});
38463
38537
  "chat.message": async (messageInput) => {
38464
38538
  const sid = messageInput.sessionID ?? messageInput.sessionId ?? messageInput.id;
38465
38539
  warmSessionDirectory(input.client, sid, input.directory);
38540
+ signalSyncWatchAbort(sid);
38466
38541
  },
38467
38542
  "tool.execute.before": async (toolInput) => {
38468
38543
  if (toolInput.sessionID)
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Per-session abort flags for sync bash_watch waits.
3
+ *
4
+ * When a user sends a message while the agent is blocked in a sync
5
+ * bash_watch wait, the `chat.message` hook sets an abort flag for that
6
+ * session. The sync wait poll loop checks the flag each iteration and
7
+ * on abort: (1) stops blocking, (2) auto-registers the equivalent async
8
+ * watch so the completion/pattern notification still arrives, (3) returns
9
+ * text telling the agent the wait converted to async.
10
+ *
11
+ * Edge cases:
12
+ * - The flag is cleared at sync-wait start so stale flags from previous
13
+ * turns don't insta-abort a new wait.
14
+ * - A wait that already matched/exited wins over abort (the flag is
15
+ * checked only at the top of the poll loop, after match/exit checks).
16
+ * - Subagent sessions behave identically — the flag is keyed by sessionID.
17
+ */
18
+ /** Signal that a sync watch for this session should abort. */
19
+ export declare function signalSyncWatchAbort(sessionID: string | undefined): void;
20
+ /** Clear any stale abort flag at the start of a new sync wait. */
21
+ export declare function clearSyncWatchAbort(sessionID: string | undefined): void;
22
+ /** Check whether the abort flag is set for this session. Does NOT clear it. */
23
+ export declare function isSyncWatchAborted(sessionID: string | undefined): boolean;
24
+ /** Test-only: reset all abort flags. */
25
+ export declare function __resetSyncWatchAbortForTests(): void;
26
+ //# sourceMappingURL=sync-watch-abort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-watch-abort.d.ts","sourceRoot":"","sources":["../src/sync-watch-abort.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,8DAA8D;AAC9D,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGxE;AAED,kEAAkE;AAClE,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAGvE;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAGzE;AAED,wCAAwC;AACxC,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD"}
@@ -9,7 +9,7 @@ export type BashWaitPattern = {
9
9
  source: string;
10
10
  };
11
11
  export type BashStatusWaited = {
12
- reason: "matched" | "exited" | "timeout";
12
+ reason: "matched" | "exited" | "timeout" | "user_message";
13
13
  elapsed_ms: number;
14
14
  match?: string;
15
15
  match_offset?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"bash_watch.d.ts","sourceRoot":"","sources":["../../src/tools/bash_watch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAavE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AACF,KAAK,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAGlF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAwFtE;AAiDD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,kBAAkB,CAAC,CA4D7B;AA6DD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAK5E;AA4DD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAEtC"}
1
+ {"version":3,"file":"bash_watch.d.ts","sourceRoot":"","sources":["../../src/tools/bash_watch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAcvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AASjD,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,cAAc,CAAC;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AACF,KAAK,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAGlF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,aAAa,GAAG,cAAc,CAwGtE;AA8GD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,OAAO,EAAE,eAAe,GAAG,SAAS,EACpC,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,kBAAkB,CAAC,CAuE7B;AA6DD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAK5E;AA4DD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,eAAe,GACvB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAEtC"}
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.37.0";
4
+ var version = "0.37.1";
5
5
 
6
6
  // src/shared/rpc-client.ts
7
7
  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.37.0",
3
+ "version": "0.37.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",
@@ -30,19 +30,19 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@clack/prompts": "^1.2.0",
33
- "@cortexkit/aft-bridge": "0.37.0",
33
+ "@cortexkit/aft-bridge": "0.37.1",
34
34
  "@xterm/headless": "^5.5.0",
35
35
  "comment-json": "^4.6.2",
36
36
  "undici": "^7.25.0",
37
37
  "zod": "^4.1.8"
38
38
  },
39
39
  "optionalDependencies": {
40
- "@cortexkit/aft-darwin-arm64": "0.37.0",
41
- "@cortexkit/aft-darwin-x64": "0.37.0",
42
- "@cortexkit/aft-linux-arm64": "0.37.0",
43
- "@cortexkit/aft-linux-x64": "0.37.0",
44
- "@cortexkit/aft-win32-arm64": "0.37.0",
45
- "@cortexkit/aft-win32-x64": "0.37.0"
40
+ "@cortexkit/aft-darwin-arm64": "0.37.1",
41
+ "@cortexkit/aft-darwin-x64": "0.37.1",
42
+ "@cortexkit/aft-linux-arm64": "0.37.1",
43
+ "@cortexkit/aft-linux-x64": "0.37.1",
44
+ "@cortexkit/aft-win32-arm64": "0.37.1",
45
+ "@cortexkit/aft-win32-x64": "0.37.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@opencode-ai/plugin": "^1.15.11",