oh-my-opencode 3.5.2 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -7052,6 +7052,12 @@ var init_tmux = __esm(() => {
7052
7052
  var init_model_suggestion_retry = __esm(() => {
7053
7053
  init_logger();
7054
7054
  });
7055
+
7056
+ // src/shared/opencode-server-auth.ts
7057
+ var init_opencode_server_auth = __esm(() => {
7058
+ init_logger();
7059
+ });
7060
+
7055
7061
  // src/shared/port-utils.ts
7056
7062
  async function isPortAvailable(port, hostname = "127.0.0.1") {
7057
7063
  try {
@@ -7128,6 +7134,7 @@ var init_shared = __esm(() => {
7128
7134
  init_session_utils();
7129
7135
  init_tmux();
7130
7136
  init_model_suggestion_retry();
7137
+ init_opencode_server_auth();
7131
7138
  init_port_utils();
7132
7139
  init_git_worktree();
7133
7140
  init_safe_create_hook();
@@ -8870,7 +8877,7 @@ var {
8870
8877
  // package.json
8871
8878
  var package_default = {
8872
8879
  name: "oh-my-opencode",
8873
- version: "3.5.2",
8880
+ version: "3.5.3",
8874
8881
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
8875
8882
  main: "dist/index.js",
8876
8883
  types: "dist/index.d.ts",
@@ -8944,13 +8951,13 @@ var package_default = {
8944
8951
  typescript: "^5.7.3"
8945
8952
  },
8946
8953
  optionalDependencies: {
8947
- "oh-my-opencode-darwin-arm64": "3.5.2",
8948
- "oh-my-opencode-darwin-x64": "3.5.2",
8949
- "oh-my-opencode-linux-arm64": "3.5.2",
8950
- "oh-my-opencode-linux-arm64-musl": "3.5.2",
8951
- "oh-my-opencode-linux-x64": "3.5.2",
8952
- "oh-my-opencode-linux-x64-musl": "3.5.2",
8953
- "oh-my-opencode-windows-x64": "3.5.2"
8954
+ "oh-my-opencode-darwin-arm64": "3.5.3",
8955
+ "oh-my-opencode-darwin-x64": "3.5.3",
8956
+ "oh-my-opencode-linux-arm64": "3.5.3",
8957
+ "oh-my-opencode-linux-arm64-musl": "3.5.3",
8958
+ "oh-my-opencode-linux-x64": "3.5.3",
8959
+ "oh-my-opencode-linux-x64-musl": "3.5.3",
8960
+ "oh-my-opencode-windows-x64": "3.5.3"
8954
8961
  },
8955
8962
  trustedDependencies: [
8956
8963
  "@ast-grep/cli",
@@ -24752,11 +24759,14 @@ async function areAllDescendantsIdle(ctx, sessionID, allStatuses) {
24752
24759
  var DEFAULT_POLL_INTERVAL_MS = 500;
24753
24760
  var DEFAULT_REQUIRED_CONSECUTIVE = 3;
24754
24761
  var ERROR_GRACE_CYCLES = 3;
24762
+ var MIN_STABILIZATION_MS = 1e4;
24755
24763
  async function pollForCompletion(ctx, eventState, abortController, options = {}) {
24756
24764
  const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
24757
24765
  const requiredConsecutive = options.requiredConsecutive ?? DEFAULT_REQUIRED_CONSECUTIVE;
24766
+ const minStabilizationMs = options.minStabilizationMs ?? MIN_STABILIZATION_MS;
24758
24767
  let consecutiveCompleteChecks = 0;
24759
24768
  let errorCycleCount = 0;
24769
+ let firstWorkTimestamp = null;
24760
24770
  while (!abortController.signal.aborted) {
24761
24771
  await new Promise((resolve2) => setTimeout(resolve2, pollIntervalMs));
24762
24772
  if (eventState.mainSessionError) {
@@ -24784,6 +24794,13 @@ Session ended with error: ${eventState.lastError}`));
24784
24794
  consecutiveCompleteChecks = 0;
24785
24795
  continue;
24786
24796
  }
24797
+ if (firstWorkTimestamp === null) {
24798
+ firstWorkTimestamp = Date.now();
24799
+ }
24800
+ if (Date.now() - firstWorkTimestamp < minStabilizationMs) {
24801
+ consecutiveCompleteChecks = 0;
24802
+ continue;
24803
+ }
24787
24804
  const shouldExit = await checkCompletionConditions(ctx);
24788
24805
  if (shouldExit) {
24789
24806
  consecutiveCompleteChecks++;
@@ -24848,7 +24865,7 @@ Interrupted. Shutting down...`));
24848
24865
  });
24849
24866
  console.log(import_picocolors14.default.dim(`Session: ${sessionID}`));
24850
24867
  const ctx = { client: client3, sessionID, directory, abortController };
24851
- const events = await client3.event.subscribe();
24868
+ const events = await client3.event.subscribe({ query: { directory } });
24852
24869
  const eventState = createEventState();
24853
24870
  const eventProcessor = processEvents(ctx, events.stream, eventState).catch(() => {});
24854
24871
  console.log(import_picocolors14.default.dim(`
@@ -3,5 +3,6 @@ import type { EventState } from "./events";
3
3
  export interface PollOptions {
4
4
  pollIntervalMs?: number;
5
5
  requiredConsecutive?: number;
6
+ minStabilizationMs?: number;
6
7
  }
7
8
  export declare function pollForCompletion(ctx: RunContext, eventState: EventState, abortController: AbortController, options?: PollOptions): Promise<number>;
@@ -7,6 +7,7 @@ export declare function handleBackgroundEvent(args: {
7
7
  event: Event;
8
8
  findBySession: (sessionID: string) => BackgroundTask | undefined;
9
9
  getAllDescendantTasks: (sessionID: string) => BackgroundTask[];
10
+ releaseConcurrencyKey?: (key: string) => void;
10
11
  cancelTask: (taskId: string, options: {
11
12
  source: string;
12
13
  reason: string;
@@ -114,6 +114,8 @@ export declare class BackgroundManager {
114
114
  private formatDuration;
115
115
  private isAbortedSessionError;
116
116
  private getErrorText;
117
+ private isRecord;
118
+ private getSessionErrorMessage;
117
119
  private hasRunningTasks;
118
120
  private pruneStaleTasksAndNotifications;
119
121
  private checkAndInterruptStaleTasks;
@@ -0,0 +1,10 @@
1
+ import type { BackgroundTask } from "./types";
2
+ export declare function handleSessionIdleBackgroundEvent(args: {
3
+ properties: Record<string, unknown>;
4
+ findBySession: (sessionID: string) => BackgroundTask | undefined;
5
+ idleDeferralTimers: Map<string, ReturnType<typeof setTimeout>>;
6
+ validateSessionHasOutput: (sessionID: string) => Promise<boolean>;
7
+ checkSessionTodos: (sessionID: string) => Promise<boolean>;
8
+ tryCompleteTask: (task: BackgroundTask, source: string) => Promise<boolean>;
9
+ emitIdleEvent: (sessionID: string) => void;
10
+ }): void;
@@ -0,0 +1,10 @@
1
+ import type { BackgroundTask } from "./types";
2
+ export declare function cleanupTaskAfterSessionEnds(args: {
3
+ task: BackgroundTask;
4
+ tasks: Map<string, BackgroundTask>;
5
+ idleDeferralTimers: Map<string, ReturnType<typeof setTimeout>>;
6
+ completionTimers: Map<string, ReturnType<typeof setTimeout>>;
7
+ cleanupPendingByParent: (task: BackgroundTask) => void;
8
+ clearNotificationsForTask: (taskId: string) => void;
9
+ releaseConcurrencyKey?: (key: string) => void;
10
+ }): void;
@@ -1,9 +1,15 @@
1
- import type { BackgroundTask } from "./types";
1
+ import type { BackgroundTask, LaunchInput } from "./types";
2
2
  import type { ConcurrencyManager } from "./concurrency";
3
+ type QueueItem = {
4
+ task: BackgroundTask;
5
+ input: LaunchInput;
6
+ };
3
7
  export declare function pruneStaleState(args: {
4
8
  tasks: Map<string, BackgroundTask>;
5
9
  notifications: Map<string, BackgroundTask[]>;
10
+ queuesByKey: Map<string, QueueItem[]>;
6
11
  concurrencyManager: ConcurrencyManager;
7
12
  cleanupPendingByParent: (task: BackgroundTask) => void;
8
13
  clearNotificationsForTask: (taskId: string) => void;
9
14
  }): void;
15
+ export {};
@@ -0,0 +1 @@
1
+ export declare function isPrometheusAgent(agentName: string | undefined): boolean;
package/dist/index.js CHANGED
@@ -34314,6 +34314,7 @@ async function promptSyncWithModelSuggestionRetry(client, args) {
34314
34314
  }
34315
34315
  }
34316
34316
  // src/shared/opencode-server-auth.ts
34317
+ init_logger();
34317
34318
  function getServerBasicAuthHeader() {
34318
34319
  const password = process.env.OPENCODE_SERVER_PASSWORD;
34319
34320
  if (!password) {
@@ -34323,27 +34324,128 @@ function getServerBasicAuthHeader() {
34323
34324
  const token = Buffer.from(`${username}:${password}`, "utf8").toString("base64");
34324
34325
  return `Basic ${token}`;
34325
34326
  }
34327
+ function isRecord(value) {
34328
+ return typeof value === "object" && value !== null;
34329
+ }
34330
+ function isRequestFetch(value) {
34331
+ return typeof value === "function";
34332
+ }
34333
+ function wrapRequestFetch(baseFetch, auth) {
34334
+ return async (request) => {
34335
+ const headers = new Headers(request.headers);
34336
+ headers.set("Authorization", auth);
34337
+ return baseFetch(new Request(request, { headers }));
34338
+ };
34339
+ }
34340
+ function getInternalClient(client) {
34341
+ if (!isRecord(client)) {
34342
+ return null;
34343
+ }
34344
+ const internal = client["_client"];
34345
+ return isRecord(internal) ? internal : null;
34346
+ }
34347
+ function tryInjectViaSetConfigHeaders(internal, auth) {
34348
+ const setConfig = internal["setConfig"];
34349
+ if (typeof setConfig !== "function") {
34350
+ return false;
34351
+ }
34352
+ setConfig({
34353
+ headers: {
34354
+ Authorization: auth
34355
+ }
34356
+ });
34357
+ return true;
34358
+ }
34359
+ function tryInjectViaInterceptors(internal, auth) {
34360
+ const interceptors = internal["interceptors"];
34361
+ if (!isRecord(interceptors)) {
34362
+ return false;
34363
+ }
34364
+ const requestInterceptors = interceptors["request"];
34365
+ if (!isRecord(requestInterceptors)) {
34366
+ return false;
34367
+ }
34368
+ const use = requestInterceptors["use"];
34369
+ if (typeof use !== "function") {
34370
+ return false;
34371
+ }
34372
+ use((request) => {
34373
+ if (!request.headers.get("Authorization")) {
34374
+ request.headers.set("Authorization", auth);
34375
+ }
34376
+ return request;
34377
+ });
34378
+ return true;
34379
+ }
34380
+ function tryInjectViaFetchWrapper(internal, auth) {
34381
+ const getConfig = internal["getConfig"];
34382
+ const setConfig = internal["setConfig"];
34383
+ if (typeof getConfig !== "function" || typeof setConfig !== "function") {
34384
+ return false;
34385
+ }
34386
+ const config2 = getConfig();
34387
+ if (!isRecord(config2)) {
34388
+ return false;
34389
+ }
34390
+ const fetchValue = config2["fetch"];
34391
+ if (!isRequestFetch(fetchValue)) {
34392
+ return false;
34393
+ }
34394
+ setConfig({
34395
+ fetch: wrapRequestFetch(fetchValue, auth)
34396
+ });
34397
+ return true;
34398
+ }
34399
+ function tryInjectViaMutableInternalConfig(internal, auth) {
34400
+ const configValue = internal["_config"];
34401
+ if (!isRecord(configValue)) {
34402
+ return false;
34403
+ }
34404
+ const fetchValue = configValue["fetch"];
34405
+ if (!isRequestFetch(fetchValue)) {
34406
+ return false;
34407
+ }
34408
+ configValue["fetch"] = wrapRequestFetch(fetchValue, auth);
34409
+ return true;
34410
+ }
34411
+ function tryInjectViaTopLevelFetch(client, auth) {
34412
+ if (!isRecord(client)) {
34413
+ return false;
34414
+ }
34415
+ const fetchValue = client["fetch"];
34416
+ if (!isRequestFetch(fetchValue)) {
34417
+ return false;
34418
+ }
34419
+ client["fetch"] = wrapRequestFetch(fetchValue, auth);
34420
+ return true;
34421
+ }
34326
34422
  function injectServerAuthIntoClient(client) {
34327
34423
  const auth = getServerBasicAuthHeader();
34328
34424
  if (!auth) {
34329
34425
  return;
34330
34426
  }
34331
34427
  try {
34332
- if (typeof client !== "object" || client === null || !("_client" in client) || typeof client._client !== "object" || client._client === null) {
34333
- throw new Error("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but SDK client structure is incompatible. " + "This may indicate an OpenCode SDK version mismatch.");
34428
+ const internal = getInternalClient(client);
34429
+ if (internal) {
34430
+ const injectedHeaders = tryInjectViaSetConfigHeaders(internal, auth);
34431
+ const injectedInterceptors = tryInjectViaInterceptors(internal, auth);
34432
+ const injectedFetch = tryInjectViaFetchWrapper(internal, auth);
34433
+ const injectedMutable = tryInjectViaMutableInternalConfig(internal, auth);
34434
+ const injected2 = injectedHeaders || injectedInterceptors || injectedFetch || injectedMutable;
34435
+ if (!injected2) {
34436
+ log("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but SDK client structure is incompatible", {
34437
+ keys: Object.keys(internal)
34438
+ });
34439
+ }
34440
+ return;
34334
34441
  }
34335
- const internal = client._client;
34336
- if (typeof internal.setConfig !== "function") {
34337
- throw new Error("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but SDK client._client.setConfig is not a function. " + "This may indicate an OpenCode SDK version mismatch.");
34442
+ const injected = tryInjectViaTopLevelFetch(client, auth);
34443
+ if (!injected) {
34444
+ log("[opencode-server-auth] OPENCODE_SERVER_PASSWORD is set but no compatible SDK client found");
34338
34445
  }
34339
- internal.setConfig({
34340
- headers: {
34341
- Authorization: auth
34342
- }
34343
- });
34344
34446
  } catch (error45) {
34345
34447
  const message = error45 instanceof Error ? error45.message : String(error45);
34346
- console.warn(`[opencode-server-auth] Failed to inject server auth: ${message}`);
34448
+ log("[opencode-server-auth] Failed to inject server auth", { message });
34347
34449
  }
34348
34450
  }
34349
34451
  // src/shared/git-worktree/parse-status-porcelain.ts
@@ -42711,7 +42813,7 @@ async function executeSlashCommand(parsed, options) {
42711
42813
  if (!command) {
42712
42814
  return {
42713
42815
  success: false,
42714
- error: `Command "/${parsed.command}" not found. Use the slashcommand tool to list available commands.`
42816
+ error: parsed.command.includes(":") ? `Marketplace plugin commands like "/${parsed.command}" are not supported. Use .claude/commands/ for custom commands.` : `Command "/${parsed.command}" not found. Use the slashcommand tool to list available commands.`
42715
42817
  };
42716
42818
  }
42717
42819
  try {
@@ -42984,6 +43086,11 @@ function getAgentFromSession(sessionID, directory) {
42984
43086
  return getAgentFromMessageFiles(sessionID);
42985
43087
  }
42986
43088
 
43089
+ // src/hooks/prometheus-md-only/agent-matcher.ts
43090
+ function isPrometheusAgent(agentName) {
43091
+ return agentName?.toLowerCase().includes(PROMETHEUS_AGENT) ?? false;
43092
+ }
43093
+
42987
43094
  // src/hooks/prometheus-md-only/path-policy.ts
42988
43095
  import { relative as relative3, resolve as resolve7, isAbsolute as isAbsolute3 } from "path";
42989
43096
  function isAllowedFile(filePath, workspaceRoot) {
@@ -43008,7 +43115,7 @@ function createPrometheusMdOnlyHook(ctx) {
43008
43115
  return {
43009
43116
  "tool.execute.before": async (input, output) => {
43010
43117
  const agentName = getAgentFromSession(input.sessionID, ctx.directory);
43011
- if (agentName !== PROMETHEUS_AGENT) {
43118
+ if (!isPrometheusAgent(agentName)) {
43012
43119
  return;
43013
43120
  }
43014
43121
  const toolName = input.tool;
@@ -44410,16 +44517,16 @@ var THINKING_SUMMARY_MAX_CHARS = 500;
44410
44517
  function hasData(value) {
44411
44518
  return typeof value === "object" && value !== null && "data" in value;
44412
44519
  }
44413
- function isRecord(value) {
44520
+ function isRecord2(value) {
44414
44521
  return typeof value === "object" && value !== null;
44415
44522
  }
44416
44523
  function getMessageInfo(value) {
44417
- if (!isRecord(value))
44524
+ if (!isRecord2(value))
44418
44525
  return;
44419
- if (!isRecord(value.info))
44526
+ if (!isRecord2(value.info))
44420
44527
  return;
44421
44528
  const info = value.info;
44422
- const modelValue = isRecord(info.model) ? info.model : undefined;
44529
+ const modelValue = isRecord2(info.model) ? info.model : undefined;
44423
44530
  const model = modelValue && typeof modelValue.providerID === "string" && typeof modelValue.modelID === "string" ? { providerID: modelValue.providerID, modelID: modelValue.modelID } : undefined;
44424
44531
  return {
44425
44532
  role: typeof info.role === "string" ? info.role : undefined,
@@ -44430,11 +44537,11 @@ function getMessageInfo(value) {
44430
44537
  };
44431
44538
  }
44432
44539
  function getMessageParts(value) {
44433
- if (!isRecord(value))
44540
+ if (!isRecord2(value))
44434
44541
  return [];
44435
44542
  if (!Array.isArray(value.parts))
44436
44543
  return [];
44437
- return value.parts.filter(isRecord).map((part) => ({
44544
+ return value.parts.filter(isRecord2).map((part) => ({
44438
44545
  type: typeof part.type === "string" ? part.type : undefined,
44439
44546
  text: typeof part.text === "string" ? part.text : undefined,
44440
44547
  thinking: typeof part.thinking === "string" ? part.thinking : undefined
@@ -47834,7 +47941,9 @@ Provide a command or skill name to execute.`;
47834
47941
 
47835
47942
  ${formatCommandList(allItems)}`;
47836
47943
  }
47837
- return `Command or skill "/${commandName}" not found.
47944
+ return commandName.includes(":") ? `Marketplace plugin commands like "/${commandName}" are not supported. Use .claude/commands/ for custom commands.
47945
+
47946
+ ${formatCommandList(allItems)}` : `Command or skill "/${commandName}" not found.
47838
47947
 
47839
47948
  ${formatCommandList(allItems)}
47840
47949
 
@@ -50213,7 +50322,8 @@ Use \`background_output\` with task_id="${task.id}" to check progress.
50213
50322
 
50214
50323
  <task_metadata>
50215
50324
  session_id: ${task.sessionID}
50216
- </task_metadata>`;
50325
+ ${task.agent ? `subagent: ${task.agent}
50326
+ ` : ""}</task_metadata>`;
50217
50327
  } catch (error45) {
50218
50328
  return formatDetailedError(error45, {
50219
50329
  operation: "Continue background task",
@@ -50666,7 +50776,8 @@ ${result.textContent || "(No text output)"}
50666
50776
 
50667
50777
  <task_metadata>
50668
50778
  session_id: ${args.session_id}
50669
- </task_metadata>`;
50779
+ ${resumeAgent ? `subagent: ${resumeAgent}
50780
+ ` : ""}</task_metadata>`;
50670
50781
  } finally {
50671
50782
  if (toastManager) {
50672
50783
  toastManager.removeTask(taskId);
@@ -52764,7 +52875,7 @@ class BackgroundManager {
52764
52875
  while (queue && queue.length > 0) {
52765
52876
  const item = queue[0];
52766
52877
  await this.concurrencyManager.acquire(key);
52767
- if (item.task.status === "cancelled") {
52878
+ if (item.task.status === "cancelled" || item.task.status === "error") {
52768
52879
  this.concurrencyManager.release(key);
52769
52880
  queue.shift();
52770
52881
  continue;
@@ -53188,6 +53299,38 @@ class BackgroundManager {
53188
53299
  log("[background-agent] Error in session.idle handler:", err);
53189
53300
  });
53190
53301
  }
53302
+ if (event.type === "session.error") {
53303
+ const sessionID = typeof props?.sessionID === "string" ? props.sessionID : undefined;
53304
+ if (!sessionID)
53305
+ return;
53306
+ const task = this.findBySession(sessionID);
53307
+ if (!task || task.status !== "running")
53308
+ return;
53309
+ const errorMessage = props ? this.getSessionErrorMessage(props) : undefined;
53310
+ task.status = "error";
53311
+ task.error = errorMessage ?? "Session error";
53312
+ task.completedAt = new Date;
53313
+ if (task.concurrencyKey) {
53314
+ this.concurrencyManager.release(task.concurrencyKey);
53315
+ task.concurrencyKey = undefined;
53316
+ }
53317
+ const completionTimer = this.completionTimers.get(task.id);
53318
+ if (completionTimer) {
53319
+ clearTimeout(completionTimer);
53320
+ this.completionTimers.delete(task.id);
53321
+ }
53322
+ const idleTimer = this.idleDeferralTimers.get(task.id);
53323
+ if (idleTimer) {
53324
+ clearTimeout(idleTimer);
53325
+ this.idleDeferralTimers.delete(task.id);
53326
+ }
53327
+ this.cleanupPendingByParent(task);
53328
+ this.tasks.delete(task.id);
53329
+ this.clearNotificationsForTask(task.id);
53330
+ if (task.sessionID) {
53331
+ subagentSessions.delete(task.sessionID);
53332
+ }
53333
+ }
53191
53334
  if (event.type === "session.deleted") {
53192
53335
  const info = props?.info;
53193
53336
  if (!info || typeof info.id !== "string")
@@ -53610,6 +53753,22 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
53610
53753
  }
53611
53754
  return "";
53612
53755
  }
53756
+ isRecord(value) {
53757
+ return typeof value === "object" && value !== null;
53758
+ }
53759
+ getSessionErrorMessage(properties) {
53760
+ const errorRaw = properties["error"];
53761
+ if (!this.isRecord(errorRaw))
53762
+ return;
53763
+ const dataRaw = errorRaw["data"];
53764
+ if (this.isRecord(dataRaw)) {
53765
+ const message2 = dataRaw["message"];
53766
+ if (typeof message2 === "string")
53767
+ return message2;
53768
+ }
53769
+ const message = errorRaw["message"];
53770
+ return typeof message === "string" ? message : undefined;
53771
+ }
53613
53772
  hasRunningTasks() {
53614
53773
  for (const task of this.tasks.values()) {
53615
53774
  if (task.status === "running")
@@ -53620,6 +53779,7 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
53620
53779
  pruneStaleTasksAndNotifications() {
53621
53780
  const now = Date.now();
53622
53781
  for (const [taskId, task] of this.tasks.entries()) {
53782
+ const wasPending = task.status === "pending";
53623
53783
  const timestamp2 = task.status === "pending" ? task.queuedAt?.getTime() : task.startedAt?.getTime();
53624
53784
  if (!timestamp2) {
53625
53785
  continue;
@@ -53636,6 +53796,19 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
53636
53796
  task.concurrencyKey = undefined;
53637
53797
  }
53638
53798
  this.cleanupPendingByParent(task);
53799
+ if (wasPending) {
53800
+ const key = task.model ? `${task.model.providerID}/${task.model.modelID}` : task.agent;
53801
+ const queue = this.queuesByKey.get(key);
53802
+ if (queue) {
53803
+ const index = queue.findIndex((item) => item.task.id === taskId);
53804
+ if (index !== -1) {
53805
+ queue.splice(index, 1);
53806
+ if (queue.length === 0) {
53807
+ this.queuesByKey.delete(key);
53808
+ }
53809
+ }
53810
+ }
53811
+ }
53639
53812
  this.clearNotificationsForTask(taskId);
53640
53813
  this.tasks.delete(taskId);
53641
53814
  if (task.sessionID) {
@@ -58082,7 +58255,7 @@ async function getOrRegisterClient(options) {
58082
58255
  }
58083
58256
  }
58084
58257
  function parseRegistrationResponse(data) {
58085
- if (!isRecord2(data))
58258
+ if (!isRecord3(data))
58086
58259
  return null;
58087
58260
  const clientId = data.client_id;
58088
58261
  if (typeof clientId !== "string" || clientId.length === 0)
@@ -58093,7 +58266,7 @@ function parseRegistrationResponse(data) {
58093
58266
  }
58094
58267
  return { clientId };
58095
58268
  }
58096
- function isRecord2(value) {
58269
+ function isRecord3(value) {
58097
58270
  return typeof value === "object" && value !== null;
58098
58271
  }
58099
58272
 
@@ -63598,7 +63771,7 @@ function maybeCreateAtlasConfig(input) {
63598
63771
  function sanitizeMarkdownTableCell(value) {
63599
63772
  return value.replace(/\r?\n/g, " ").replace(/\|/g, "\\|").replace(/\s+/g, " ").trim();
63600
63773
  }
63601
- function isRecord3(value) {
63774
+ function isRecord4(value) {
63602
63775
  return typeof value === "object" && value !== null;
63603
63776
  }
63604
63777
  function parseRegisteredAgentSummaries(input) {
@@ -63606,7 +63779,7 @@ function parseRegisteredAgentSummaries(input) {
63606
63779
  return [];
63607
63780
  const result = [];
63608
63781
  for (const item of input) {
63609
- if (!isRecord3(item))
63782
+ if (!isRecord4(item))
63610
63783
  continue;
63611
63784
  const name = typeof item.name === "string" ? item.name : undefined;
63612
63785
  if (!name)
@@ -66894,11 +67067,11 @@ async function createTools(args) {
66894
67067
  }
66895
67068
 
66896
67069
  // src/plugin/chat-params.ts
66897
- function isRecord4(value) {
67070
+ function isRecord5(value) {
66898
67071
  return typeof value === "object" && value !== null;
66899
67072
  }
66900
67073
  function buildChatParamsInput(raw) {
66901
- if (!isRecord4(raw))
67074
+ if (!isRecord5(raw))
66902
67075
  return null;
66903
67076
  const sessionID = raw.sessionID;
66904
67077
  const agent = raw.agent;
@@ -66909,11 +67082,11 @@ function buildChatParamsInput(raw) {
66909
67082
  return null;
66910
67083
  if (typeof agent !== "string")
66911
67084
  return null;
66912
- if (!isRecord4(model))
67085
+ if (!isRecord5(model))
66913
67086
  return null;
66914
- if (!isRecord4(provider))
67087
+ if (!isRecord5(provider))
66915
67088
  return null;
66916
- if (!isRecord4(message))
67089
+ if (!isRecord5(message))
66917
67090
  return null;
66918
67091
  const providerID = model.providerID;
66919
67092
  const modelID = model.modelID;
@@ -66934,12 +67107,12 @@ function buildChatParamsInput(raw) {
66934
67107
  };
66935
67108
  }
66936
67109
  function isChatParamsOutput(raw) {
66937
- if (!isRecord4(raw))
67110
+ if (!isRecord5(raw))
66938
67111
  return false;
66939
- if (!isRecord4(raw.options)) {
67112
+ if (!isRecord5(raw.options)) {
66940
67113
  raw.options = {};
66941
67114
  }
66942
- return isRecord4(raw.options);
67115
+ return isRecord5(raw.options);
66943
67116
  }
66944
67117
  function createChatParamsHandler(args) {
66945
67118
  return async (input, output) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "3.5.2",
3
+ "version": "3.5.3",
4
4
  "description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -74,13 +74,13 @@
74
74
  "typescript": "^5.7.3"
75
75
  },
76
76
  "optionalDependencies": {
77
- "oh-my-opencode-darwin-arm64": "3.5.2",
78
- "oh-my-opencode-darwin-x64": "3.5.2",
79
- "oh-my-opencode-linux-arm64": "3.5.2",
80
- "oh-my-opencode-linux-arm64-musl": "3.5.2",
81
- "oh-my-opencode-linux-x64": "3.5.2",
82
- "oh-my-opencode-linux-x64-musl": "3.5.2",
83
- "oh-my-opencode-windows-x64": "3.5.2"
77
+ "oh-my-opencode-darwin-arm64": "3.5.3",
78
+ "oh-my-opencode-darwin-x64": "3.5.3",
79
+ "oh-my-opencode-linux-arm64": "3.5.3",
80
+ "oh-my-opencode-linux-arm64-musl": "3.5.3",
81
+ "oh-my-opencode-linux-x64": "3.5.3",
82
+ "oh-my-opencode-linux-x64-musl": "3.5.3",
83
+ "oh-my-opencode-windows-x64": "3.5.3"
84
84
  },
85
85
  "trustedDependencies": [
86
86
  "@ast-grep/cli",