@liangjie559567/ultrapower 5.4.8 → 5.5.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.
Files changed (82) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/bridge/codex-server.cjs +3 -3
  4. package/bridge/gemini-server.cjs +6 -5
  5. package/bridge/mcp-server.cjs +82 -4
  6. package/bridge/team-bridge.cjs +400 -55
  7. package/dist/features/auto-update.d.ts.map +1 -1
  8. package/dist/features/auto-update.js +3 -1
  9. package/dist/features/auto-update.js.map +1 -1
  10. package/dist/features/rate-limit-wait/daemon.d.ts.map +1 -1
  11. package/dist/features/rate-limit-wait/daemon.js +39 -6
  12. package/dist/features/rate-limit-wait/daemon.js.map +1 -1
  13. package/dist/hooks/__tests__/bridge-security.test.js +94 -1
  14. package/dist/hooks/__tests__/bridge-security.test.js.map +1 -1
  15. package/dist/hooks/bridge-normalize.d.ts.map +1 -1
  16. package/dist/hooks/bridge-normalize.js +5 -2
  17. package/dist/hooks/bridge-normalize.js.map +1 -1
  18. package/dist/hooks/recovery/session-recovery.js +1 -1
  19. package/dist/hooks/recovery/session-recovery.js.map +1 -1
  20. package/dist/hooks/subagent-tracker/__tests__/syncSleep.test.d.ts +10 -0
  21. package/dist/hooks/subagent-tracker/__tests__/syncSleep.test.d.ts.map +1 -0
  22. package/dist/hooks/subagent-tracker/__tests__/syncSleep.test.js +112 -0
  23. package/dist/hooks/subagent-tracker/__tests__/syncSleep.test.js.map +1 -0
  24. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
  25. package/dist/hooks/subagent-tracker/index.js +39 -7
  26. package/dist/hooks/subagent-tracker/index.js.map +1 -1
  27. package/dist/lib/__tests__/atomic-write.test.d.ts +2 -0
  28. package/dist/lib/__tests__/atomic-write.test.d.ts.map +1 -0
  29. package/dist/lib/__tests__/atomic-write.test.js +197 -0
  30. package/dist/lib/__tests__/atomic-write.test.js.map +1 -0
  31. package/dist/mcp/__tests__/gemini-yolo-env.test.d.ts +2 -0
  32. package/dist/mcp/__tests__/gemini-yolo-env.test.d.ts.map +1 -0
  33. package/dist/mcp/__tests__/gemini-yolo-env.test.js +274 -0
  34. package/dist/mcp/__tests__/gemini-yolo-env.test.js.map +1 -0
  35. package/dist/mcp/gemini-core.d.ts +1 -0
  36. package/dist/mcp/gemini-core.d.ts.map +1 -1
  37. package/dist/mcp/gemini-core.js +11 -2
  38. package/dist/mcp/gemini-core.js.map +1 -1
  39. package/dist/mcp/job-management.d.ts.map +1 -1
  40. package/dist/mcp/job-management.js +2 -4
  41. package/dist/mcp/job-management.js.map +1 -1
  42. package/dist/notifications/__tests__/sleepMs.test.d.ts +10 -0
  43. package/dist/notifications/__tests__/sleepMs.test.d.ts.map +1 -0
  44. package/dist/notifications/__tests__/sleepMs.test.js +117 -0
  45. package/dist/notifications/__tests__/sleepMs.test.js.map +1 -0
  46. package/dist/notifications/session-registry.d.ts.map +1 -1
  47. package/dist/notifications/session-registry.js +35 -2
  48. package/dist/notifications/session-registry.js.map +1 -1
  49. package/dist/team/mcp-team-bridge.d.ts.map +1 -1
  50. package/dist/team/mcp-team-bridge.js +2 -1
  51. package/dist/team/mcp-team-bridge.js.map +1 -1
  52. package/dist/tools/__tests__/state-tools.test.js +76 -0
  53. package/dist/tools/__tests__/state-tools.test.js.map +1 -1
  54. package/dist/tools/lsp/__tests__/client-timer-buffer.test.d.ts +11 -0
  55. package/dist/tools/lsp/__tests__/client-timer-buffer.test.d.ts.map +1 -0
  56. package/dist/tools/lsp/__tests__/client-timer-buffer.test.js +222 -0
  57. package/dist/tools/lsp/__tests__/client-timer-buffer.test.js.map +1 -0
  58. package/dist/tools/lsp/__tests__/command-exists.test.d.ts +2 -0
  59. package/dist/tools/lsp/__tests__/command-exists.test.d.ts.map +1 -0
  60. package/dist/tools/lsp/__tests__/command-exists.test.js +104 -0
  61. package/dist/tools/lsp/__tests__/command-exists.test.js.map +1 -0
  62. package/dist/tools/lsp/client.d.ts.map +1 -1
  63. package/dist/tools/lsp/client.js +15 -0
  64. package/dist/tools/lsp/client.js.map +1 -1
  65. package/dist/tools/lsp/servers.d.ts +7 -1
  66. package/dist/tools/lsp/servers.d.ts.map +1 -1
  67. package/dist/tools/lsp/servers.js +14 -3
  68. package/dist/tools/lsp/servers.js.map +1 -1
  69. package/dist/tools/python-repl/tool.d.ts.map +1 -1
  70. package/dist/tools/python-repl/tool.js +4 -0
  71. package/dist/tools/python-repl/tool.js.map +1 -1
  72. package/dist/tools/state-tools.d.ts +9 -8
  73. package/dist/tools/state-tools.d.ts.map +1 -1
  74. package/dist/tools/state-tools.js +44 -1
  75. package/dist/tools/state-tools.js.map +1 -1
  76. package/docs/reviews/draft-prd-ultrapower-pain-fix/review_tech.md +219 -0
  77. package/docs/reviews/draft_prd_pain_points/review_domain.md +215 -0
  78. package/docs/reviews/ultrapower-full-bugfix-plan/review_product.md +135 -0
  79. package/docs/reviews/ultrapower-pain-points/review_critic.md +181 -0
  80. package/docs/reviews/ultrapower-pain-points/review_ux.md +167 -0
  81. package/package.json +1 -1
  82. package/skills/ax-export/SKILL.md +39 -6
@@ -8,11 +8,11 @@
8
8
  {
9
9
  "name": "ultrapower",
10
10
  "description": "Disciplined multi-agent orchestration: workflow enforcement + parallel execution",
11
- "version": "5.4.8",
11
+ "version": "5.5.0",
12
12
  "source": {
13
13
  "source": "npm",
14
14
  "package": "@liangjie559567/ultrapower",
15
- "version": "5.4.8"
15
+ "version": "5.5.0"
16
16
  },
17
17
  "author": {
18
18
  "name": "liangjie559567"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ultrapower",
3
3
  "description": "Disciplined multi-agent orchestration: workflow enforcement + parallel execution. Combines superpowers' TDD/debugging discipline with OMC's multi-agent execution capabilities.",
4
- "version": "5.4.8",
4
+ "version": "5.5.0",
5
5
  "author": {
6
6
  "name": "liangjie559567"
7
7
  },
@@ -17323,6 +17323,7 @@ function isSpawnedPid2(pid) {
17323
17323
  }
17324
17324
  var GEMINI_DEFAULT_MODEL = process.env.OMC_GEMINI_DEFAULT_MODEL || "gemini-3-pro-preview";
17325
17325
  var GEMINI_TIMEOUT = Math.min(Math.max(5e3, parseInt(process.env.OMC_GEMINI_TIMEOUT || "3600000", 10) || 36e5), 36e5);
17326
+ var _yoloEnv = process.env.OMC_GEMINI_YOLO;
17326
17327
  var MAX_FILE_SIZE2 = 5 * 1024 * 1024;
17327
17328
  var MAX_STDOUT_BYTES2 = 10 * 1024 * 1024;
17328
17329
 
@@ -17388,7 +17389,7 @@ async function handleWaitForJob(provider, jobId, timeoutMs = 36e5) {
17388
17389
  if (!jobId || typeof jobId !== "string") {
17389
17390
  return textResult("job_id is required.", true);
17390
17391
  }
17391
- const effectiveTimeout = Math.max(1e3, Math.min(timeoutMs, 36e5));
17392
+ const effectiveTimeout = Math.max(1e3, Math.min(timeoutMs, 6e4));
17392
17393
  const deadline = Date.now() + effectiveTimeout;
17393
17394
  let pollDelay = 500;
17394
17395
  let notFoundCount = 0;
@@ -17608,7 +17609,6 @@ async function handleKillJob(provider, jobId, signal = "SIGTERM") {
17608
17609
  ...status,
17609
17610
  killedByUser: true
17610
17611
  };
17611
- writeJobStatus(updated);
17612
17612
  try {
17613
17613
  if (process.platform !== "win32") {
17614
17614
  process.kill(-status.pid, signal);
@@ -17800,7 +17800,7 @@ function getJobManagementToolSchemas(_provider) {
17800
17800
  },
17801
17801
  timeout_ms: {
17802
17802
  type: "number",
17803
- description: "Maximum time to wait in milliseconds (default: 3600000, max: 3600000)."
17803
+ description: "Maximum time to wait in milliseconds (default: 3600000, max: 60000)."
17804
17804
  }
17805
17805
  },
17806
17806
  required: ["job_id"]
@@ -16374,6 +16374,8 @@ function validateModelName(model) {
16374
16374
  }
16375
16375
  var GEMINI_DEFAULT_MODEL = process.env.OMC_GEMINI_DEFAULT_MODEL || "gemini-3-pro-preview";
16376
16376
  var GEMINI_TIMEOUT = Math.min(Math.max(5e3, parseInt(process.env.OMC_GEMINI_TIMEOUT || "3600000", 10) || 36e5), 36e5);
16377
+ var _yoloEnv = process.env.OMC_GEMINI_YOLO;
16378
+ var GEMINI_YOLO = _yoloEnv === "false" || _yoloEnv === "0" ? false : true;
16377
16379
  var GEMINI_RECOMMENDED_ROLES = ["designer", "writer", "vision"];
16378
16380
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
16379
16381
  var MAX_STDOUT_BYTES = 10 * 1024 * 1024;
@@ -16394,7 +16396,7 @@ function executeGemini(prompt, model, cwd) {
16394
16396
  return new Promise((resolve7, reject) => {
16395
16397
  if (model) validateModelName(model);
16396
16398
  let settled = false;
16397
- const args = ["-p=.", "--yolo"];
16399
+ const args = ["-p=.", ...GEMINI_YOLO ? ["--yolo"] : []];
16398
16400
  if (model) {
16399
16401
  args.push("--model", model);
16400
16402
  }
@@ -16469,7 +16471,7 @@ function executeGeminiBackground(fullPrompt, modelInput, jobMeta, workingDirecto
16469
16471
  const modelsToTry = modelExplicit ? [effectiveModel] : GEMINI_MODEL_FALLBACKS.includes(effectiveModel) ? GEMINI_MODEL_FALLBACKS.slice(GEMINI_MODEL_FALLBACKS.indexOf(effectiveModel)) : [effectiveModel, ...GEMINI_MODEL_FALLBACKS];
16470
16472
  const trySpawnWithModel = (tryModel, remainingModels) => {
16471
16473
  validateModelName(tryModel);
16472
- const args = ["-p=.", "--yolo", "--model", tryModel];
16474
+ const args = ["-p=.", ...GEMINI_YOLO ? ["--yolo"] : [], "--model", tryModel];
16473
16475
  const child = (0, import_child_process3.spawn)("gemini", args, {
16474
16476
  detached: process.platform !== "win32",
16475
16477
  stdio: ["pipe", "pipe", "pipe"],
@@ -17031,7 +17033,7 @@ async function handleWaitForJob(provider, jobId, timeoutMs = 36e5) {
17031
17033
  if (!jobId || typeof jobId !== "string") {
17032
17034
  return textResult("job_id is required.", true);
17033
17035
  }
17034
- const effectiveTimeout = Math.max(1e3, Math.min(timeoutMs, 36e5));
17036
+ const effectiveTimeout = Math.max(1e3, Math.min(timeoutMs, 6e4));
17035
17037
  const deadline = Date.now() + effectiveTimeout;
17036
17038
  let pollDelay = 500;
17037
17039
  let notFoundCount = 0;
@@ -17251,7 +17253,6 @@ async function handleKillJob(provider, jobId, signal = "SIGTERM") {
17251
17253
  ...status,
17252
17254
  killedByUser: true
17253
17255
  };
17254
- writeJobStatus(updated);
17255
17256
  try {
17256
17257
  if (process.platform !== "win32") {
17257
17258
  process.kill(-status.pid, signal);
@@ -17443,7 +17444,7 @@ function getJobManagementToolSchemas(_provider) {
17443
17444
  },
17444
17445
  timeout_ms: {
17445
17446
  type: "number",
17446
- description: "Maximum time to wait in milliseconds (default: 3600000, max: 3600000)."
17447
+ description: "Maximum time to wait in milliseconds (default: 3600000, max: 60000)."
17447
17448
  }
17448
17449
  },
17449
17450
  required: ["job_id"]
@@ -17913,9 +17913,12 @@ var LSP_SERVERS = {
17913
17913
  }
17914
17914
  };
17915
17915
  function commandExists(command) {
17916
+ if (!command || !command.trim()) {
17917
+ return false;
17918
+ }
17916
17919
  try {
17917
17920
  const checkCommand = process.platform === "win32" ? "where" : "which";
17918
- (0, import_child_process.execSync)(`${checkCommand} ${command}`, { stdio: "ignore" });
17921
+ (0, import_child_process.execFileSync)(checkCommand, [command], { stdio: "ignore" });
17919
17922
  return true;
17920
17923
  } catch {
17921
17924
  return false;
@@ -17938,6 +17941,7 @@ function getAllServers() {
17938
17941
  }
17939
17942
 
17940
17943
  // src/tools/lsp/client.ts
17944
+ var MAX_BUFFER_BYTES = 64 * 1024 * 1024;
17941
17945
  function fileUri(filePath) {
17942
17946
  return (0, import_url.pathToFileURL)((0, import_path2.resolve)(filePath)).href;
17943
17947
  }
@@ -18011,6 +18015,10 @@ Install with: ${this.serverConfig.installHint}`
18011
18015
  this.process.kill();
18012
18016
  this.process = null;
18013
18017
  this.initialized = false;
18018
+ for (const [, pending] of this.pendingRequests) {
18019
+ clearTimeout(pending.timeout);
18020
+ pending.reject(new Error("LSP client disconnected"));
18021
+ }
18014
18022
  this.pendingRequests.clear();
18015
18023
  this.openDocuments.clear();
18016
18024
  this.diagnostics.clear();
@@ -18019,6 +18027,14 @@ Install with: ${this.serverConfig.installHint}`
18019
18027
  * Handle incoming data from the server
18020
18028
  */
18021
18029
  handleData(data) {
18030
+ if (this.buffer.length + data.length > MAX_BUFFER_BYTES) {
18031
+ console.error(
18032
+ `[ultrapower] \u9519\u8BEF\uFF1ALSP \u7F13\u51B2\u533A\u8D85\u8FC7 ${MAX_BUFFER_BYTES} \u5B57\u8282\uFF0864MB\uFF09\u4E0A\u9650\uFF0C\u6B63\u5728\u65AD\u5F00\u8FDE\u63A5`
18033
+ );
18034
+ this.disconnect().catch(() => {
18035
+ });
18036
+ return;
18037
+ }
18022
18038
  this.buffer += data;
18023
18039
  while (true) {
18024
18040
  const headerEnd = this.buffer.indexOf("\r\n\r\n");
@@ -20909,9 +20925,11 @@ async function handleExecute(sessionId, socketPath, code, executionTimeout, exec
20909
20925
  async function handleReset(sessionId, socketPath) {
20910
20926
  try {
20911
20927
  const result = await sendSocketRequest(socketPath, "reset", {}, 1e4);
20928
+ resetExecutionCounter(sessionId);
20912
20929
  return formatResetResult(result, sessionId);
20913
20930
  } catch (_error) {
20914
20931
  await killBridgeWithEscalation(sessionId);
20932
+ resetExecutionCounter(sessionId);
20915
20933
  return [
20916
20934
  "=== Bridge Restarted ===",
20917
20935
  `Session: ${sessionId}`,
@@ -20951,6 +20969,7 @@ async function handleInterrupt(sessionId, socketPath, gracePeriodMs = 5e3) {
20951
20969
  {},
20952
20970
  Math.min(gracePeriodMs, 5e3)
20953
20971
  );
20972
+ resetExecutionCounter(sessionId);
20954
20973
  return formatInterruptResult(
20955
20974
  {
20956
20975
  ...result,
@@ -20961,6 +20980,7 @@ async function handleInterrupt(sessionId, socketPath, gracePeriodMs = 5e3) {
20961
20980
  );
20962
20981
  } catch {
20963
20982
  const escalationResult = await killBridgeWithEscalation(sessionId, { gracePeriodMs });
20983
+ resetExecutionCounter(sessionId);
20964
20984
  return formatInterruptResult(
20965
20985
  {
20966
20986
  status: "force_killed",
@@ -21113,6 +21133,9 @@ var pythonReplTool = {
21113
21133
  };
21114
21134
  }
21115
21135
  };
21136
+ function resetExecutionCounter(sessionId) {
21137
+ executionCounters.delete(sessionId);
21138
+ }
21116
21139
 
21117
21140
  // src/tools/state-tools.ts
21118
21141
  var import_fs8 = require("fs");
@@ -21491,8 +21514,33 @@ function getActiveSessionsForMode(mode, cwd) {
21491
21514
  return sessionIds.filter((sid) => isJsonModeActive(cwd, mode, sid));
21492
21515
  }
21493
21516
 
21517
+ // src/lib/validateMode.ts
21518
+ var VALID_MODES = [
21519
+ "autopilot",
21520
+ "ultrapilot",
21521
+ "team",
21522
+ "pipeline",
21523
+ "ralph",
21524
+ "ultrawork",
21525
+ "ultraqa",
21526
+ "swarm"
21527
+ ];
21528
+ function validateMode(mode) {
21529
+ return typeof mode === "string" && VALID_MODES.includes(mode);
21530
+ }
21531
+ function assertValidMode(mode) {
21532
+ if (!validateMode(mode)) {
21533
+ const raw = typeof mode === "string" ? mode : String(mode);
21534
+ const display = raw.length > 50 ? `${raw.slice(0, 50)}...(truncated)` : raw;
21535
+ throw new Error(
21536
+ `Invalid mode: "${display}". Valid modes are: ${VALID_MODES.join(", ")}`
21537
+ );
21538
+ }
21539
+ return mode;
21540
+ }
21541
+
21494
21542
  // src/tools/state-tools.ts
21495
- var EXECUTION_MODES = [
21543
+ var STATE_TOOL_MODES = [
21496
21544
  "autopilot",
21497
21545
  "ultrapilot",
21498
21546
  "swarm",
@@ -21500,9 +21548,9 @@ var EXECUTION_MODES = [
21500
21548
  "team",
21501
21549
  "ralph",
21502
21550
  "ultrawork",
21503
- "ultraqa"
21551
+ "ultraqa",
21552
+ "ralplan"
21504
21553
  ];
21505
- var STATE_TOOL_MODES = [...EXECUTION_MODES, "ralplan"];
21506
21554
  function getStatePath(mode, root) {
21507
21555
  if (MODE_CONFIGS[mode]) {
21508
21556
  return getStateFilePath(root, mode);
@@ -21520,6 +21568,16 @@ var stateReadTool = {
21520
21568
  handler: async (args) => {
21521
21569
  const { mode, workingDirectory, session_id } = args;
21522
21570
  try {
21571
+ if (mode !== "ralplan") {
21572
+ try {
21573
+ assertValidMode(mode);
21574
+ } catch {
21575
+ return {
21576
+ content: [{ type: "text", text: `[ultrapower] \u9519\u8BEF\uFF1A\u65E0\u6548\u7684\u72B6\u6001\u6A21\u5F0F\uFF1A${mode}` }],
21577
+ isError: true
21578
+ };
21579
+ }
21580
+ }
21523
21581
  const root = validateWorkingDirectory(workingDirectory);
21524
21582
  const sessionId = session_id;
21525
21583
  if (mode === "swarm") {
@@ -21696,6 +21754,16 @@ var stateWriteTool = {
21696
21754
  session_id
21697
21755
  } = args;
21698
21756
  try {
21757
+ if (mode !== "ralplan") {
21758
+ try {
21759
+ assertValidMode(mode);
21760
+ } catch {
21761
+ return {
21762
+ content: [{ type: "text", text: `[ultrapower] \u9519\u8BEF\uFF1A\u65E0\u6548\u7684\u72B6\u6001\u6A21\u5F0F\uFF1A${mode}` }],
21763
+ isError: true
21764
+ };
21765
+ }
21766
+ }
21699
21767
  const root = validateWorkingDirectory(workingDirectory);
21700
21768
  const sessionId = session_id;
21701
21769
  if (mode === "swarm") {
@@ -21778,6 +21846,16 @@ var stateClearTool = {
21778
21846
  handler: async (args) => {
21779
21847
  const { mode, workingDirectory, session_id } = args;
21780
21848
  try {
21849
+ if (mode !== "ralplan") {
21850
+ try {
21851
+ assertValidMode(mode);
21852
+ } catch {
21853
+ return {
21854
+ content: [{ type: "text", text: `[ultrapower] \u9519\u8BEF\uFF1A\u65E0\u6548\u7684\u72B6\u6001\u6A21\u5F0F\uFF1A${mode}` }],
21855
+ isError: true
21856
+ };
21857
+ }
21858
+ }
21781
21859
  const root = validateWorkingDirectory(workingDirectory);
21782
21860
  const sessionId = session_id;
21783
21861
  if (sessionId) {