oh-my-opencode-unguarded 3.10.3 → 3.10.4

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/README.md CHANGED
@@ -38,6 +38,12 @@ All features, configuration, and guides apply as-is:
38
38
  - [Installation Guide](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/docs/guide/installation.md)
39
39
  - [Orchestration Guide](https://github.com/code-yeongyu/oh-my-opencode/blob/dev/docs/guide/orchestration.md)
40
40
 
41
+ Even only with following subscriptions, ultrawork will work well (this project is not affiliated, this is just personal recommendation):
42
+ - [ChatGPT Subscription ($20)](https://chatgpt.com/)
43
+ - [Kimi Code Subscription ($0.99) (*only this month)](https://www.kimi.com/kimiplus/sale)
44
+ - [GLM Coding Plan ($10)](https://z.ai/subscribe)
45
+ - If you are eligible for pay-per-token, using kimi and gemini models won't cost you that much.
46
+
41
47
  ## License
42
48
 
43
49
  Same as upstream -- [SUL-1.0](LICENSE.md)
@@ -7,3 +7,4 @@ export interface LoadedVersionInfo {
7
7
  }
8
8
  export declare function getLoadedPluginVersion(): LoadedVersionInfo;
9
9
  export declare function getLatestPluginVersion(currentVersion: string | null): Promise<string | null>;
10
+ export declare function getSuggestedInstallTag(currentVersion: string | null): string;
package/dist/cli/index.js CHANGED
@@ -9442,7 +9442,7 @@ var {
9442
9442
  // package.json
9443
9443
  var package_default = {
9444
9444
  name: "oh-my-opencode-unguarded",
9445
- version: "3.10.3",
9445
+ version: "3.10.4",
9446
9446
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
9447
9447
  main: "dist/index.js",
9448
9448
  types: "dist/index.d.ts",
@@ -26945,6 +26945,9 @@ async function getLatestPluginVersion(currentVersion) {
26945
26945
  const channel = extractChannel(currentVersion);
26946
26946
  return getLatestVersion(channel);
26947
26947
  }
26948
+ function getSuggestedInstallTag(currentVersion) {
26949
+ return extractChannel(currentVersion);
26950
+ }
26948
26951
 
26949
26952
  // src/cli/doctor/checks/system.ts
26950
26953
  init_shared();
@@ -26994,6 +26997,7 @@ async function checkSystem() {
26994
26997
  const [systemInfo, pluginInfo] = await Promise.all([gatherSystemInfo(), Promise.resolve(getPluginInfo())]);
26995
26998
  const loadedInfo = getLoadedPluginVersion();
26996
26999
  const latestVersion = await getLatestPluginVersion(systemInfo.loadedVersion);
27000
+ const installTag = getSuggestedInstallTag(systemInfo.loadedVersion);
26997
27001
  const issues = [];
26998
27002
  if (!systemInfo.opencodePath) {
26999
27003
  issues.push({
@@ -27026,7 +27030,7 @@ async function checkSystem() {
27026
27030
  issues.push({
27027
27031
  title: "Loaded plugin version mismatch",
27028
27032
  description: `Cache expects ${loadedInfo.expectedVersion} but loaded ${loadedInfo.loadedVersion}.`,
27029
- fix: `Reinstall: cd ${loadedInfo.cacheDir} && bun install`,
27033
+ fix: `Reinstall: cd "${loadedInfo.cacheDir}" && bun install`,
27030
27034
  severity: "warning",
27031
27035
  affects: ["plugin loading"]
27032
27036
  });
@@ -27035,7 +27039,7 @@ async function checkSystem() {
27035
27039
  issues.push({
27036
27040
  title: "Loaded plugin is outdated",
27037
27041
  description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
27038
- fix: `Update: cd ${loadedInfo.cacheDir} && bun add oh-my-opencode@latest`,
27042
+ fix: `Update: cd "${loadedInfo.cacheDir}" && bun add oh-my-opencode@${installTag}`,
27039
27043
  severity: "warning",
27040
27044
  affects: ["plugin features"]
27041
27045
  });
package/dist/index.js CHANGED
@@ -17662,7 +17662,7 @@ function resolveModelPipeline(request) {
17662
17662
  const normalizedUserModel = normalizeModel(intent?.userModel);
17663
17663
  if (normalizedUserModel) {
17664
17664
  log("Model resolved via config override", { model: normalizedUserModel });
17665
- return { model: normalizedUserModel, provenance: "override", explicitUserConfig: true };
17665
+ return { model: normalizedUserModel, provenance: "override" };
17666
17666
  }
17667
17667
  const normalizedCategoryDefault = normalizeModel(intent?.categoryDefaultModel);
17668
17668
  if (normalizedCategoryDefault) {
@@ -20470,12 +20470,14 @@ async function sendSessionNotification(ctx, platform2, title, message) {
20470
20470
  const terminalNotifierPath = await getTerminalNotifierPath();
20471
20471
  if (terminalNotifierPath) {
20472
20472
  const bundleId = process.env.__CFBundleIdentifier;
20473
- const args = [terminalNotifierPath, "-title", title, "-message", message];
20474
- if (bundleId) {
20475
- args.push("-activate", bundleId);
20476
- }
20477
- await ctx.$`${args}`.catch(() => {});
20478
- break;
20473
+ try {
20474
+ if (bundleId) {
20475
+ await ctx.$`${terminalNotifierPath} -title ${title} -message ${message} -activate ${bundleId}`;
20476
+ } else {
20477
+ await ctx.$`${terminalNotifierPath} -title ${title} -message ${message}`;
20478
+ }
20479
+ break;
20480
+ } catch {}
20479
20481
  }
20480
20482
  const osascriptPath = await getOsascriptPath();
20481
20483
  if (!osascriptPath)
@@ -56312,9 +56314,9 @@ async function resolveMultimodalLookerAgentMetadata(ctx) {
56312
56314
 
56313
56315
  // src/tools/look-at/image-converter.ts
56314
56316
  import { execFileSync as execFileSync3 } from "child_process";
56315
- import { existsSync as existsSync68, mkdtempSync, unlinkSync as unlinkSync9, writeFileSync as writeFileSync19, readFileSync as readFileSync46 } from "fs";
56317
+ import { existsSync as existsSync68, mkdtempSync, readFileSync as readFileSync46, rmSync as rmSync3, unlinkSync as unlinkSync9, writeFileSync as writeFileSync19 } from "fs";
56316
56318
  import { tmpdir as tmpdir6 } from "os";
56317
- import { join as join73 } from "path";
56319
+ import { dirname as dirname20, join as join73 } from "path";
56318
56320
  var SUPPORTED_FORMATS = new Set([
56319
56321
  "image/jpeg",
56320
56322
  "image/png",
@@ -56341,6 +56343,7 @@ var UNSUPPORTED_FORMATS = new Set([
56341
56343
  "image/vnd.adobe.photoshop",
56342
56344
  "image/x-photoshop"
56343
56345
  ]);
56346
+ var CONVERSION_TIMEOUT_MS = 30000;
56344
56347
  function needsConversion(mimeType) {
56345
56348
  if (SUPPORTED_FORMATS.has(mimeType)) {
56346
56349
  return false;
@@ -56360,9 +56363,10 @@ function convertImageToJpeg(inputPath, mimeType) {
56360
56363
  try {
56361
56364
  if (process.platform === "darwin") {
56362
56365
  try {
56363
- execFileSync3("sips", ["-s", "format", "jpeg", inputPath, "--out", outputPath], {
56366
+ execFileSync3("sips", ["-s", "format", "jpeg", "--", inputPath, "--out", outputPath], {
56364
56367
  stdio: "pipe",
56365
- encoding: "utf-8"
56368
+ encoding: "utf-8",
56369
+ timeout: CONVERSION_TIMEOUT_MS
56366
56370
  });
56367
56371
  if (existsSync68(outputPath)) {
56368
56372
  log(`[image-converter] Converted using sips: ${outputPath}`);
@@ -56373,9 +56377,11 @@ function convertImageToJpeg(inputPath, mimeType) {
56373
56377
  }
56374
56378
  }
56375
56379
  try {
56376
- execFileSync3("convert", [inputPath, outputPath], {
56380
+ const imagemagickCommand = process.platform === "darwin" ? "convert" : "magick";
56381
+ execFileSync3(imagemagickCommand, ["--", inputPath, outputPath], {
56377
56382
  stdio: "pipe",
56378
- encoding: "utf-8"
56383
+ encoding: "utf-8",
56384
+ timeout: CONVERSION_TIMEOUT_MS
56379
56385
  });
56380
56386
  if (existsSync68(outputPath)) {
56381
56387
  log(`[image-converter] Converted using ImageMagick: ${outputPath}`);
@@ -56394,15 +56400,24 @@ function convertImageToJpeg(inputPath, mimeType) {
56394
56400
  unlinkSync9(outputPath);
56395
56401
  }
56396
56402
  } catch {}
56403
+ if (error45 instanceof Error) {
56404
+ const conversionError = error45;
56405
+ conversionError.temporaryOutputPath = outputPath;
56406
+ }
56397
56407
  throw error45;
56398
56408
  }
56399
56409
  }
56400
56410
  function cleanupConvertedImage(filePath) {
56401
56411
  try {
56412
+ const tempDirectory = dirname20(filePath);
56402
56413
  if (existsSync68(filePath)) {
56403
56414
  unlinkSync9(filePath);
56404
56415
  log(`[image-converter] Cleaned up temporary file: ${filePath}`);
56405
56416
  }
56417
+ if (existsSync68(tempDirectory)) {
56418
+ rmSync3(tempDirectory, { recursive: true, force: true });
56419
+ log(`[image-converter] Cleaned up temporary directory: ${tempDirectory}`);
56420
+ }
56406
56421
  } catch (error45) {
56407
56422
  log(`[image-converter] Failed to cleanup ${filePath}: ${error45}`);
56408
56423
  }
@@ -56435,6 +56450,20 @@ function convertBase64ImageToJpeg(base64Data, mimeType) {
56435
56450
  }
56436
56451
 
56437
56452
  // src/tools/look-at/tools.ts
56453
+ function getTemporaryConversionPath(error45) {
56454
+ if (!(error45 instanceof Error)) {
56455
+ return null;
56456
+ }
56457
+ const temporaryOutputPath = Reflect.get(error45, "temporaryOutputPath");
56458
+ if (typeof temporaryOutputPath === "string" && temporaryOutputPath.length > 0) {
56459
+ return temporaryOutputPath;
56460
+ }
56461
+ const temporaryDirectory = Reflect.get(error45, "temporaryDirectory");
56462
+ if (typeof temporaryDirectory === "string" && temporaryDirectory.length > 0) {
56463
+ return temporaryDirectory;
56464
+ }
56465
+ return null;
56466
+ }
56438
56467
  function createLookAt(ctx) {
56439
56468
  return tool({
56440
56469
  description: LOOK_AT_DESCRIPTION,
@@ -56458,6 +56487,7 @@ function createLookAt(ctx) {
56458
56487
  let mimeType;
56459
56488
  let filePart;
56460
56489
  let tempFilePath = null;
56490
+ let tempConversionPath = null;
56461
56491
  let tempFilesToCleanup = [];
56462
56492
  try {
56463
56493
  if (imageData) {
@@ -56490,10 +56520,15 @@ function createLookAt(ctx) {
56490
56520
  log(`[look_at] Detected unsupported format: ${mimeType}, converting to JPEG...`);
56491
56521
  try {
56492
56522
  tempFilePath = convertImageToJpeg(filePath, mimeType);
56523
+ tempConversionPath = tempFilePath;
56493
56524
  actualFilePath = tempFilePath;
56494
56525
  mimeType = "image/jpeg";
56495
56526
  log(`[look_at] Conversion successful: ${tempFilePath}`);
56496
56527
  } catch (conversionError) {
56528
+ const failedConversionPath = getTemporaryConversionPath(conversionError);
56529
+ if (failedConversionPath) {
56530
+ tempConversionPath = failedConversionPath;
56531
+ }
56497
56532
  log(`[look_at] Conversion failed: ${conversionError}`);
56498
56533
  return `Error: Failed to convert image format. ${conversionError}`;
56499
56534
  }
@@ -56585,10 +56620,14 @@ Original error: ${createResult.error}`;
56585
56620
  log(`[look_at] Got response, length: ${responseText.length}`);
56586
56621
  return responseText;
56587
56622
  } finally {
56588
- if (tempFilePath) {
56623
+ if (tempConversionPath) {
56624
+ cleanupConvertedImage(tempConversionPath);
56625
+ } else if (tempFilePath) {
56589
56626
  cleanupConvertedImage(tempFilePath);
56590
56627
  }
56591
- tempFilesToCleanup.forEach((file2) => cleanupConvertedImage(file2));
56628
+ tempFilesToCleanup.forEach((file2) => {
56629
+ cleanupConvertedImage(file2);
56630
+ });
56592
56631
  }
56593
56632
  }
56594
56633
  });
@@ -56894,9 +56933,13 @@ var MIN_STABILITY_TIME_MS = 1e4;
56894
56933
  var STABILITY_POLLS_REQUIRED = 3;
56895
56934
  var WAIT_FOR_SESSION_INTERVAL_MS = 100;
56896
56935
  var WAIT_FOR_SESSION_TIMEOUT_MS = 30000;
56897
- var MAX_POLL_TIME_MS = 10 * 60 * 1000;
56936
+ var DEFAULT_POLL_TIMEOUT_MS = 10 * 60 * 1000;
56937
+ var MAX_POLL_TIME_MS = DEFAULT_POLL_TIMEOUT_MS;
56898
56938
  var SESSION_CONTINUATION_STABILITY_MS = 5000;
56899
- var DEFAULT_SYNC_POLL_TIMEOUT_MS = 600000;
56939
+ var DEFAULT_SYNC_POLL_TIMEOUT_MS = DEFAULT_POLL_TIMEOUT_MS;
56940
+ function getDefaultSyncPollTimeoutMs() {
56941
+ return MAX_POLL_TIME_MS;
56942
+ }
56900
56943
  function getTimingConfig() {
56901
56944
  return {
56902
56945
  POLL_INTERVAL_MS,
@@ -56934,7 +56977,7 @@ function isSessionComplete(messages) {
56934
56977
  }
56935
56978
  async function pollSyncSession(ctx, client2, input, timeoutMs) {
56936
56979
  const syncTiming = getTimingConfig();
56937
- const maxPollTimeMs = Math.max(timeoutMs ?? DEFAULT_SYNC_POLL_TIMEOUT_MS, 50);
56980
+ const maxPollTimeMs = Math.max(timeoutMs ?? getDefaultSyncPollTimeoutMs(), 50);
56938
56981
  const pollStart = Date.now();
56939
56982
  let pollCount = 0;
56940
56983
  let timedOut = false;
@@ -57245,6 +57288,7 @@ Task ID: ${task.id}`;
57245
57288
  let lastMsgCount = 0;
57246
57289
  let stablePolls = 0;
57247
57290
  let terminalStatus;
57291
+ let completedDuringMonitoring = false;
57248
57292
  while (Date.now() - pollStart < (syncPollTimeoutMs ?? DEFAULT_SYNC_POLL_TIMEOUT_MS)) {
57249
57293
  if (ctx.abort?.aborted) {
57250
57294
  return `Task aborted (was running in background mode).
@@ -57274,8 +57318,10 @@ Session ID: ${sessionID}`;
57274
57318
  const currentMsgCount = msgs.length;
57275
57319
  if (currentMsgCount === lastMsgCount) {
57276
57320
  stablePolls++;
57277
- if (stablePolls >= timingCfg.STABILITY_POLLS_REQUIRED)
57321
+ if (stablePolls >= timingCfg.STABILITY_POLLS_REQUIRED) {
57322
+ completedDuringMonitoring = true;
57278
57323
  break;
57324
+ }
57279
57325
  } else {
57280
57326
  stablePolls = 0;
57281
57327
  lastMsgCount = currentMsgCount;
@@ -57294,6 +57340,24 @@ Model: ${actualModel}
57294
57340
 
57295
57341
  The task session may contain partial results.
57296
57342
 
57343
+ <task_metadata>
57344
+ session_id: ${sessionID}
57345
+ </task_metadata>`;
57346
+ }
57347
+ if (!completedDuringMonitoring) {
57348
+ const duration4 = formatDuration2(startTime);
57349
+ const timeoutBudgetMs = syncPollTimeoutMs ?? DEFAULT_SYNC_POLL_TIMEOUT_MS;
57350
+ return `SUPERVISED TASK TIMED OUT
57351
+
57352
+ Task did not reach a stable completion signal within the monitored timeout budget.
57353
+ Timeout budget: ${timeoutBudgetMs}ms
57354
+
57355
+ Duration: ${duration4}
57356
+ Agent: ${agentToUse}${args.category ? ` (category: ${args.category})` : ""}
57357
+ Model: ${actualModel}
57358
+
57359
+ The task session may still contain partial results.
57360
+
57297
57361
  <task_metadata>
57298
57362
  session_id: ${sessionID}
57299
57363
  </task_metadata>`;
@@ -58011,7 +58075,7 @@ Create the work plan directly - that's your job as the planning agent.`
58011
58075
  fallbackChain = agentRequirement?.fallbackChain;
58012
58076
  if (agentOverride?.model || agentRequirement || matchedAgent.model) {
58013
58077
  const availableModels = await getAvailableModelsForDelegateTask(client2);
58014
- const normalizedMatchedModel = normalizeModelFormat(matchedAgent.model);
58078
+ const normalizedMatchedModel = matchedAgent.model ? normalizeModelFormat(matchedAgent.model) : undefined;
58015
58079
  const matchedAgentModelStr = normalizedMatchedModel ? `${normalizedMatchedModel.providerID}/${normalizedMatchedModel.modelID}` : undefined;
58016
58080
  const resolution = resolveModelForDelegateTask({
58017
58081
  userModel: agentOverride?.model,
@@ -58029,7 +58093,10 @@ Create the work plan directly - that's your job as the planning agent.`
58029
58093
  }
58030
58094
  }
58031
58095
  if (!categoryModel && matchedAgent.model) {
58032
- categoryModel = matchedAgent.model;
58096
+ const normalizedMatchedModel = normalizeModelFormat(matchedAgent.model);
58097
+ if (normalizedMatchedModel) {
58098
+ categoryModel = normalizedMatchedModel;
58099
+ }
58033
58100
  }
58034
58101
  } catch (error45) {
58035
58102
  const errorMessage = error45 instanceof Error ? error45.message : String(error45);
@@ -58309,7 +58376,7 @@ var TaskDeleteInputSchema = exports_external.object({
58309
58376
  });
58310
58377
 
58311
58378
  // src/features/claude-tasks/storage.ts
58312
- import { join as join74, dirname as dirname20, basename as basename9, isAbsolute as isAbsolute8 } from "path";
58379
+ import { join as join74, dirname as dirname21, basename as basename9, isAbsolute as isAbsolute8 } from "path";
58313
58380
  import { existsSync as existsSync69, mkdirSync as mkdirSync14, readFileSync as readFileSync47, writeFileSync as writeFileSync20, renameSync, unlinkSync as unlinkSync10, readdirSync as readdirSync19 } from "fs";
58314
58381
  import { randomUUID as randomUUID2 } from "crypto";
58315
58382
  function getTaskDir(config3 = {}) {
@@ -58359,7 +58426,7 @@ function readJsonSafe(filePath, schema2) {
58359
58426
  }
58360
58427
  }
58361
58428
  function writeJsonAtomic(filePath, data) {
58362
- const dir = dirname20(filePath);
58429
+ const dir = dirname21(filePath);
58363
58430
  ensureDir(dir);
58364
58431
  const tempPath = `${filePath}.tmp.${Date.now()}`;
58365
58432
  try {
@@ -66404,7 +66471,7 @@ class StreamableHTTPClientTransport {
66404
66471
 
66405
66472
  // src/features/mcp-oauth/storage.ts
66406
66473
  import { chmodSync as chmodSync2, existsSync as existsSync71, mkdirSync as mkdirSync15, readFileSync as readFileSync49, unlinkSync as unlinkSync11, writeFileSync as writeFileSync21 } from "fs";
66407
- import { dirname as dirname21, join as join81 } from "path";
66474
+ import { dirname as dirname22, join as join81 } from "path";
66408
66475
  var STORAGE_FILE_NAME = "mcp-oauth.json";
66409
66476
  function getMcpOauthStoragePath() {
66410
66477
  return join81(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
@@ -66457,7 +66524,7 @@ function readStore() {
66457
66524
  function writeStore(store2) {
66458
66525
  const filePath = getMcpOauthStoragePath();
66459
66526
  try {
66460
- const dir = dirname21(filePath);
66527
+ const dir = dirname22(filePath);
66461
66528
  if (!existsSync71(dir)) {
66462
66529
  mkdirSync15(dir, { recursive: true });
66463
66530
  }
@@ -22,6 +22,5 @@ export type ModelResolutionResult = {
22
22
  variant?: string;
23
23
  attempted?: string[];
24
24
  reason?: string;
25
- explicitUserConfig?: boolean;
26
25
  };
27
26
  export declare function resolveModelPipeline(request: ModelResolutionRequest): ModelResolutionResult | undefined;
@@ -1,4 +1,5 @@
1
- export declare const DEFAULT_SYNC_POLL_TIMEOUT_MS = 600000;
1
+ export declare const DEFAULT_SYNC_POLL_TIMEOUT_MS: number;
2
+ export declare function getDefaultSyncPollTimeoutMs(): number;
2
3
  export declare function getTimingConfig(): {
3
4
  POLL_INTERVAL_MS: number;
4
5
  MIN_STABILITY_TIME_MS: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode-unguarded",
3
- "version": "3.10.3",
3
+ "version": "3.10.4",
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",