oh-my-opencode 3.11.1 → 3.11.2

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
@@ -8575,15 +8575,20 @@ function removeFromBunLock(packageName) {
8575
8575
  }
8576
8576
  function invalidatePackage(packageName = PACKAGE_NAME3) {
8577
8577
  try {
8578
- const pkgDir = path8.join(USER_CONFIG_DIR, "node_modules", packageName);
8578
+ const pkgDirs = [
8579
+ path8.join(USER_CONFIG_DIR, "node_modules", packageName),
8580
+ path8.join(CACHE_DIR, "node_modules", packageName)
8581
+ ];
8579
8582
  const pkgJsonPath = path8.join(USER_CONFIG_DIR, "package.json");
8580
8583
  let packageRemoved = false;
8581
8584
  let dependencyRemoved = false;
8582
8585
  let lockRemoved = false;
8583
- if (fs10.existsSync(pkgDir)) {
8584
- fs10.rmSync(pkgDir, { recursive: true, force: true });
8585
- log(`[auto-update-checker] Package removed: ${pkgDir}`);
8586
- packageRemoved = true;
8586
+ for (const pkgDir of pkgDirs) {
8587
+ if (fs10.existsSync(pkgDir)) {
8588
+ fs10.rmSync(pkgDir, { recursive: true, force: true });
8589
+ log(`[auto-update-checker] Package removed: ${pkgDir}`);
8590
+ packageRemoved = true;
8591
+ }
8587
8592
  }
8588
8593
  if (fs10.existsSync(pkgJsonPath)) {
8589
8594
  const content = fs10.readFileSync(pkgJsonPath, "utf-8");
@@ -8935,7 +8940,7 @@ var {
8935
8940
  // package.json
8936
8941
  var package_default = {
8937
8942
  name: "oh-my-opencode",
8938
- version: "3.11.1",
8943
+ version: "3.11.2",
8939
8944
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
8940
8945
  main: "dist/index.js",
8941
8946
  types: "dist/index.d.ts",
@@ -9011,17 +9016,17 @@ var package_default = {
9011
9016
  typescript: "^5.7.3"
9012
9017
  },
9013
9018
  optionalDependencies: {
9014
- "oh-my-opencode-darwin-arm64": "3.11.1",
9015
- "oh-my-opencode-darwin-x64": "3.11.1",
9016
- "oh-my-opencode-darwin-x64-baseline": "3.11.1",
9017
- "oh-my-opencode-linux-arm64": "3.11.1",
9018
- "oh-my-opencode-linux-arm64-musl": "3.11.1",
9019
- "oh-my-opencode-linux-x64": "3.11.1",
9020
- "oh-my-opencode-linux-x64-baseline": "3.11.1",
9021
- "oh-my-opencode-linux-x64-musl": "3.11.1",
9022
- "oh-my-opencode-linux-x64-musl-baseline": "3.11.1",
9023
- "oh-my-opencode-windows-x64": "3.11.1",
9024
- "oh-my-opencode-windows-x64-baseline": "3.11.1"
9019
+ "oh-my-opencode-darwin-arm64": "3.11.2",
9020
+ "oh-my-opencode-darwin-x64": "3.11.2",
9021
+ "oh-my-opencode-darwin-x64-baseline": "3.11.2",
9022
+ "oh-my-opencode-linux-arm64": "3.11.2",
9023
+ "oh-my-opencode-linux-arm64-musl": "3.11.2",
9024
+ "oh-my-opencode-linux-x64": "3.11.2",
9025
+ "oh-my-opencode-linux-x64-baseline": "3.11.2",
9026
+ "oh-my-opencode-linux-x64-musl": "3.11.2",
9027
+ "oh-my-opencode-linux-x64-musl-baseline": "3.11.2",
9028
+ "oh-my-opencode-windows-x64": "3.11.2",
9029
+ "oh-my-opencode-windows-x64-baseline": "3.11.2"
9025
9030
  },
9026
9031
  overrides: {
9027
9032
  "@opencode-ai/sdk": "^1.2.17"
@@ -8,6 +8,8 @@ type SessionNotificationConfig = {
8
8
  idleConfirmationDelay: number;
9
9
  skipIfIncompleteTodos: boolean;
10
10
  maxTrackedSessions: number;
11
+ /** Grace period in ms to ignore late-arriving activity events after scheduling (default: 100) */
12
+ activityGracePeriodMs?: number;
11
13
  };
12
14
  export declare function createIdleNotificationScheduler(options: {
13
15
  ctx: PluginInput;
@@ -13,6 +13,8 @@ interface SessionNotificationConfig {
13
13
  /** Maximum number of sessions to track before cleanup (default: 100) */
14
14
  maxTrackedSessions?: number;
15
15
  enforceMainSessionFilter?: boolean;
16
+ /** Grace period in ms to ignore late-arriving activity events after scheduling (default: 100) */
17
+ activityGracePeriodMs?: number;
16
18
  }
17
19
  export declare function createSessionNotification(ctx: PluginInput, config?: SessionNotificationConfig): ({ event }: {
18
20
  event: {
package/dist/index.js CHANGED
@@ -20801,6 +20801,8 @@ function createIdleNotificationScheduler(options) {
20801
20801
  const sessionActivitySinceIdle = new Set;
20802
20802
  const notificationVersions = new Map;
20803
20803
  const executingNotifications = new Set;
20804
+ const scheduledAt = new Map;
20805
+ const activityGracePeriodMs = options.config.activityGracePeriodMs ?? 100;
20804
20806
  function cleanupOldSessions() {
20805
20807
  const maxSessions = options.config.maxTrackedSessions;
20806
20808
  if (notifiedSessions.size > maxSessions) {
@@ -20819,6 +20821,10 @@ function createIdleNotificationScheduler(options) {
20819
20821
  const sessionsToRemove = Array.from(executingNotifications).slice(0, executingNotifications.size - maxSessions);
20820
20822
  sessionsToRemove.forEach((id) => executingNotifications.delete(id));
20821
20823
  }
20824
+ if (scheduledAt.size > maxSessions) {
20825
+ const sessionsToRemove = Array.from(scheduledAt.keys()).slice(0, scheduledAt.size - maxSessions);
20826
+ sessionsToRemove.forEach((id) => scheduledAt.delete(id));
20827
+ }
20822
20828
  }
20823
20829
  function cancelPendingNotification(sessionID) {
20824
20830
  const timer = pendingTimers.get(sessionID);
@@ -20826,10 +20832,15 @@ function createIdleNotificationScheduler(options) {
20826
20832
  clearTimeout(timer);
20827
20833
  pendingTimers.delete(sessionID);
20828
20834
  }
20835
+ scheduledAt.delete(sessionID);
20829
20836
  sessionActivitySinceIdle.add(sessionID);
20830
20837
  notificationVersions.set(sessionID, (notificationVersions.get(sessionID) ?? 0) + 1);
20831
20838
  }
20832
20839
  function markSessionActivity(sessionID) {
20840
+ const scheduledTime = scheduledAt.get(sessionID);
20841
+ if (scheduledTime && Date.now() - scheduledTime < activityGracePeriodMs) {
20842
+ return;
20843
+ }
20833
20844
  cancelPendingNotification(sessionID);
20834
20845
  if (!executingNotifications.has(sessionID)) {
20835
20846
  notifiedSessions.delete(sessionID);
@@ -20838,19 +20849,23 @@ function createIdleNotificationScheduler(options) {
20838
20849
  async function executeNotification(sessionID, version) {
20839
20850
  if (executingNotifications.has(sessionID)) {
20840
20851
  pendingTimers.delete(sessionID);
20852
+ scheduledAt.delete(sessionID);
20841
20853
  return;
20842
20854
  }
20843
20855
  if (notificationVersions.get(sessionID) !== version) {
20844
20856
  pendingTimers.delete(sessionID);
20857
+ scheduledAt.delete(sessionID);
20845
20858
  return;
20846
20859
  }
20847
20860
  if (sessionActivitySinceIdle.has(sessionID)) {
20848
20861
  sessionActivitySinceIdle.delete(sessionID);
20849
20862
  pendingTimers.delete(sessionID);
20863
+ scheduledAt.delete(sessionID);
20850
20864
  return;
20851
20865
  }
20852
20866
  if (notifiedSessions.has(sessionID)) {
20853
20867
  pendingTimers.delete(sessionID);
20868
+ scheduledAt.delete(sessionID);
20854
20869
  return;
20855
20870
  }
20856
20871
  executingNotifications.add(sessionID);
@@ -20878,6 +20893,7 @@ function createIdleNotificationScheduler(options) {
20878
20893
  } finally {
20879
20894
  executingNotifications.delete(sessionID);
20880
20895
  pendingTimers.delete(sessionID);
20896
+ scheduledAt.delete(sessionID);
20881
20897
  if (sessionActivitySinceIdle.has(sessionID)) {
20882
20898
  notifiedSessions.delete(sessionID);
20883
20899
  sessionActivitySinceIdle.delete(sessionID);
@@ -20892,6 +20908,7 @@ function createIdleNotificationScheduler(options) {
20892
20908
  if (executingNotifications.has(sessionID))
20893
20909
  return;
20894
20910
  sessionActivitySinceIdle.delete(sessionID);
20911
+ scheduledAt.set(sessionID, Date.now());
20895
20912
  const currentVersion = (notificationVersions.get(sessionID) ?? 0) + 1;
20896
20913
  notificationVersions.set(sessionID, currentVersion);
20897
20914
  const timer = setTimeout(() => {
@@ -20906,6 +20923,7 @@ function createIdleNotificationScheduler(options) {
20906
20923
  sessionActivitySinceIdle.delete(sessionID);
20907
20924
  notificationVersions.delete(sessionID);
20908
20925
  executingNotifications.delete(sessionID);
20926
+ scheduledAt.delete(sessionID);
20909
20927
  }
20910
20928
  return {
20911
20929
  markSessionActivity,
@@ -40627,15 +40645,20 @@ function removeFromBunLock(packageName) {
40627
40645
  }
40628
40646
  function invalidatePackage(packageName = PACKAGE_NAME) {
40629
40647
  try {
40630
- const pkgDir = path9.join(USER_CONFIG_DIR, "node_modules", packageName);
40648
+ const pkgDirs = [
40649
+ path9.join(USER_CONFIG_DIR, "node_modules", packageName),
40650
+ path9.join(CACHE_DIR, "node_modules", packageName)
40651
+ ];
40631
40652
  const pkgJsonPath = path9.join(USER_CONFIG_DIR, "package.json");
40632
40653
  let packageRemoved = false;
40633
40654
  let dependencyRemoved = false;
40634
40655
  let lockRemoved = false;
40635
- if (fs13.existsSync(pkgDir)) {
40636
- fs13.rmSync(pkgDir, { recursive: true, force: true });
40637
- log(`[auto-update-checker] Package removed: ${pkgDir}`);
40638
- packageRemoved = true;
40656
+ for (const pkgDir of pkgDirs) {
40657
+ if (fs13.existsSync(pkgDir)) {
40658
+ fs13.rmSync(pkgDir, { recursive: true, force: true });
40659
+ log(`[auto-update-checker] Package removed: ${pkgDir}`);
40660
+ packageRemoved = true;
40661
+ }
40639
40662
  }
40640
40663
  if (fs13.existsSync(pkgJsonPath)) {
40641
40664
  const content = fs13.readFileSync(pkgJsonPath, "utf-8");
@@ -76969,22 +76992,6 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
76969
76992
  continue;
76970
76993
  try {
76971
76994
  const sessionStatus = allStatuses[sessionID];
76972
- if (sessionStatus?.type === "idle") {
76973
- const hasValidOutput = await this.validateSessionHasOutput(sessionID);
76974
- if (!hasValidOutput) {
76975
- log("[background-agent] Polling idle but no valid output yet, waiting:", task.id);
76976
- continue;
76977
- }
76978
- if (task.status !== "running")
76979
- continue;
76980
- const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
76981
- if (hasIncompleteTodos2) {
76982
- log("[background-agent] Task has incomplete todos via polling, waiting:", task.id);
76983
- continue;
76984
- }
76985
- await this.tryCompleteTask(task, "polling (idle status)");
76986
- continue;
76987
- }
76988
76995
  if (sessionStatus?.type === "retry") {
76989
76996
  const retryMessage = typeof sessionStatus.message === "string" ? sessionStatus.message : undefined;
76990
76997
  const errorInfo = { name: "SessionRetry", message: retryMessage };
@@ -76992,12 +76999,29 @@ Use \`background_output(task_id="${task.id}")\` to retrieve this result when rea
76992
76999
  continue;
76993
77000
  }
76994
77001
  }
76995
- log("[background-agent] Session still running, relying on event-based progress:", {
76996
- taskId: task.id,
76997
- sessionID,
76998
- sessionStatus: sessionStatus?.type ?? "not_in_status",
76999
- toolCalls: task.progress?.toolCalls ?? 0
77000
- });
77002
+ if (sessionStatus && sessionStatus.type !== "idle") {
77003
+ log("[background-agent] Session still running, relying on event-based progress:", {
77004
+ taskId: task.id,
77005
+ sessionID,
77006
+ sessionStatus: sessionStatus.type,
77007
+ toolCalls: task.progress?.toolCalls ?? 0
77008
+ });
77009
+ continue;
77010
+ }
77011
+ const completionSource = sessionStatus?.type === "idle" ? "polling (idle status)" : "polling (session gone from status)";
77012
+ const hasValidOutput = await this.validateSessionHasOutput(sessionID);
77013
+ if (!hasValidOutput) {
77014
+ log("[background-agent] Polling idle/gone but no valid output yet, waiting:", task.id);
77015
+ continue;
77016
+ }
77017
+ if (task.status !== "running")
77018
+ continue;
77019
+ const hasIncompleteTodos2 = await this.checkSessionTodos(sessionID);
77020
+ if (hasIncompleteTodos2) {
77021
+ log("[background-agent] Task has incomplete todos via polling, waiting:", task.id);
77022
+ continue;
77023
+ }
77024
+ await this.tryCompleteTask(task, completionSource);
77001
77025
  } catch (error92) {
77002
77026
  log("[background-agent] Poll error for task:", { taskId: task.id, error: error92 });
77003
77027
  }
@@ -92566,6 +92590,17 @@ async function loadPluginComponents(params) {
92566
92590
  }
92567
92591
 
92568
92592
  // src/plugin-handlers/tool-config-handler.ts
92593
+ function getConfigQuestionPermission() {
92594
+ const configContent = process.env.OPENCODE_CONFIG_CONTENT;
92595
+ if (!configContent)
92596
+ return null;
92597
+ try {
92598
+ const parsed = JSON.parse(configContent);
92599
+ return parsed?.permission?.question ?? null;
92600
+ } catch {
92601
+ return null;
92602
+ }
92603
+ }
92569
92604
  function agentByKey(agentResult, key) {
92570
92605
  return agentResult[key] ?? agentResult[getAgentDisplayName(key)];
92571
92606
  }
@@ -92582,7 +92617,8 @@ function applyToolConfig(params) {
92582
92617
  ...params.pluginConfig.experimental?.task_system ? { todowrite: false, todoread: false } : {}
92583
92618
  };
92584
92619
  const isCliRunMode = process.env.OPENCODE_CLI_RUN_MODE === "true";
92585
- const questionPermission = isCliRunMode ? "deny" : "allow";
92620
+ const configQuestionPermission = getConfigQuestionPermission();
92621
+ const questionPermission = configQuestionPermission === "deny" ? "deny" : isCliRunMode ? "deny" : "allow";
92586
92622
  const librarian = agentByKey(params.agentResult, "librarian");
92587
92623
  if (librarian) {
92588
92624
  librarian.permission = { ...librarian.permission, "grep_app_*": "allow" };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "3.11.1",
3
+ "version": "3.11.2",
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",
@@ -76,17 +76,17 @@
76
76
  "typescript": "^5.7.3"
77
77
  },
78
78
  "optionalDependencies": {
79
- "oh-my-opencode-darwin-arm64": "3.11.1",
80
- "oh-my-opencode-darwin-x64": "3.11.1",
81
- "oh-my-opencode-darwin-x64-baseline": "3.11.1",
82
- "oh-my-opencode-linux-arm64": "3.11.1",
83
- "oh-my-opencode-linux-arm64-musl": "3.11.1",
84
- "oh-my-opencode-linux-x64": "3.11.1",
85
- "oh-my-opencode-linux-x64-baseline": "3.11.1",
86
- "oh-my-opencode-linux-x64-musl": "3.11.1",
87
- "oh-my-opencode-linux-x64-musl-baseline": "3.11.1",
88
- "oh-my-opencode-windows-x64": "3.11.1",
89
- "oh-my-opencode-windows-x64-baseline": "3.11.1"
79
+ "oh-my-opencode-darwin-arm64": "3.11.2",
80
+ "oh-my-opencode-darwin-x64": "3.11.2",
81
+ "oh-my-opencode-darwin-x64-baseline": "3.11.2",
82
+ "oh-my-opencode-linux-arm64": "3.11.2",
83
+ "oh-my-opencode-linux-arm64-musl": "3.11.2",
84
+ "oh-my-opencode-linux-x64": "3.11.2",
85
+ "oh-my-opencode-linux-x64-baseline": "3.11.2",
86
+ "oh-my-opencode-linux-x64-musl": "3.11.2",
87
+ "oh-my-opencode-linux-x64-musl-baseline": "3.11.2",
88
+ "oh-my-opencode-windows-x64": "3.11.2",
89
+ "oh-my-opencode-windows-x64-baseline": "3.11.2"
90
90
  },
91
91
  "overrides": {
92
92
  "@opencode-ai/sdk": "^1.2.17"