@sireai/optimus 0.1.20 → 0.1.22

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 (32) hide show
  1. package/README.md +3 -0
  2. package/dist/cli/optimus.js +130 -23
  3. package/dist/cli/optimus.js.map +1 -1
  4. package/dist/config/load-config.js +2 -1
  5. package/dist/config/load-config.js.map +1 -1
  6. package/dist/integrations/jira/jira-access-manager.d.ts +34 -0
  7. package/dist/integrations/jira/jira-access-manager.js +140 -0
  8. package/dist/integrations/jira/jira-access-manager.js.map +1 -0
  9. package/dist/integrations/jira/jira-cli.js +13 -23
  10. package/dist/integrations/jira/jira-cli.js.map +1 -1
  11. package/dist/integrations/jira/jira-client.js +2 -0
  12. package/dist/integrations/jira/jira-client.js.map +1 -1
  13. package/dist/integrations/jira/jira-submit.d.ts +2 -1
  14. package/dist/integrations/jira/jira-submit.js +15 -14
  15. package/dist/integrations/jira/jira-submit.js.map +1 -1
  16. package/dist/problem-solving-core/codex/codex-failure-classifier.js +11 -2
  17. package/dist/problem-solving-core/codex/codex-failure-classifier.js.map +1 -1
  18. package/dist/task-environment/delivery/task-publication-service.d.ts +1 -0
  19. package/dist/task-environment/delivery/task-publication-service.js +52 -44
  20. package/dist/task-environment/delivery/task-publication-service.js.map +1 -1
  21. package/dist/task-environment/intake/triage-rejection-feedback-service.d.ts +0 -1
  22. package/dist/task-environment/intake/triage-rejection-feedback-service.js +38 -32
  23. package/dist/task-environment/intake/triage-rejection-feedback-service.js.map +1 -1
  24. package/dist/task-environment/orchestration/task-orchestrator.js +1 -1
  25. package/dist/task-environment/orchestration/triage-runner.d.ts +1 -0
  26. package/dist/task-environment/orchestration/triage-runner.js +10 -2
  27. package/dist/task-environment/orchestration/triage-runner.js.map +1 -1
  28. package/dist/types.d.ts +1 -0
  29. package/embedded-skills/task/bugfix/android-debug-protocol/SKILL.md +10 -0
  30. package/embedded-skills/task/bugfix/android-debug-protocol/skill.json +6 -0
  31. package/optimus.config.template.json +1 -1
  32. package/package.json +1 -1
package/README.md CHANGED
@@ -102,9 +102,12 @@ Jira intake:
102
102
 
103
103
  ```bash
104
104
  optimus jira-submit-issue --issue-key MICARAPPI-13178 --repo mobile-app
105
+ optimus jira-submit-issue --issue-key MICARAPPI-13178 --repo mobile-app --with-comments
105
106
  optimus jira-refresh-auth --issue-key MICARAPPI-13178
106
107
  ```
107
108
 
109
+ `jira-submit-issue` now excludes Jira comments by default. Add `--with-comments` when recent comments should be included in the submit context. `--comment-limit` only applies when `--with-comments` is set.
110
+
108
111
  Sentry intake:
109
112
 
110
113
  ```bash
@@ -292,12 +292,16 @@ function renderCommandHelp(command) {
292
292
  "",
293
293
  "Usage:",
294
294
  " optimus submit --title <title> --description <text> [options]",
295
+ " optimus submit --title <title> --description-file <path> [options]",
296
+ " printf '%s' '<text>' | optimus submit --title <title> --description-stdin [options]",
295
297
  "",
296
298
  "Required:",
297
299
  " --title <title> Task title",
298
300
  " --description <text> Task description",
299
301
  "",
300
302
  "Common options:",
303
+ " --description-file <path> Read task description from a file",
304
+ " --description-stdin Read task description from stdin",
301
305
  " --repo <alias> Target registered repository alias",
302
306
  " --task-type <type> Task type, default bugfix",
303
307
  " --source-ref <id> External issue key or source reference",
@@ -311,11 +315,17 @@ function renderCommandHelp(command) {
311
315
  "",
312
316
  "Usage:",
313
317
  " optimus feedback --title <title> --description <text>",
318
+ " optimus feedback --title <title> --description-file <path>",
319
+ " printf '%s' '<text>' | optimus feedback --title <title> --description-stdin",
314
320
  "",
315
321
  "Required:",
316
322
  " --title <title> Feedback title",
317
323
  " --description <text> Feedback description",
318
324
  "",
325
+ "Optional text sources:",
326
+ " --description-file <path> Read feedback description from a file",
327
+ " --description-stdin Read feedback description from stdin",
328
+ "",
319
329
  "Behavior:",
320
330
  " - writes a local feedback bundle under ~/.optimus/runtime/feedback",
321
331
  " - creates a .tar.gz archive for the bundle",
@@ -325,7 +335,8 @@ function renderCommandHelp(command) {
325
335
  " - sends a Feishu app card message with the feedback document link",
326
336
  "",
327
337
  "Example:",
328
- " optimus feedback --title \"Upgrade prompt missing\" --description \"upgrade --check found 0.1.14 but start did not open the upgrade prompt.\""
338
+ " optimus feedback --title \"Upgrade prompt missing\" --description \"upgrade --check found 0.1.14 but start did not open the upgrade prompt.\"",
339
+ " optimus feedback --title \"Shell quoting issue\" --description-file ./feedback.txt"
329
340
  ].join("\n"),
330
341
  "retry-task": [
331
342
  "optimus retry-task",
@@ -476,7 +487,8 @@ function renderCommandHelp(command) {
476
487
  " --branch <name> Override target branch",
477
488
  " --task-type <type> Task type, default bugfix",
478
489
  " --allow-duplicate Allow duplicate submission",
479
- " --comment-limit <n> Comment lines fetched from Jira, default 3",
490
+ " --with-comments Include recent Jira comments in submit context",
491
+ " --comment-limit <n> Comment lines fetched from Jira when --with-comments is set, default 3",
480
492
  " --dry-run Preview without creating a task",
481
493
  "",
482
494
  "Example:",
@@ -493,6 +505,7 @@ function renderCommandHelp(command) {
493
505
  " --repo <alias> Target registered repository alias",
494
506
  " --projects-filter <csv> Restrict Jira projects",
495
507
  " --limit <n> Max issues to submit, default 50",
508
+ " --with-comments Include recent Jira comments in submit context",
496
509
  " --allow-duplicate Allow duplicate submission",
497
510
  " --dry-run Preview without creating tasks"
498
511
  ].join("\n"),
@@ -1708,19 +1721,70 @@ function summarizeIssue(issue, fallback) {
1708
1721
  }
1709
1722
  return issue.message.replace(/\.$/u, "");
1710
1723
  }
1724
+ function isCodexModelSelectionFailure(healthCheck) {
1725
+ const normalized = healthCheck.summary.toLowerCase();
1726
+ return normalized.includes("model_not_found")
1727
+ || normalized.includes("unsupported model")
1728
+ || normalized.includes("invalid model")
1729
+ || (normalized.includes("requested model") && normalized.includes("does not exist"))
1730
+ || (normalized.includes("model") && normalized.includes("not supported"));
1731
+ }
1732
+ function isCodexQuotaFailure(healthCheck) {
1733
+ const normalized = healthCheck.summary.toLowerCase();
1734
+ return normalized.includes("quota exceeded")
1735
+ || normalized.includes("billing details")
1736
+ || normalized.includes("insufficient_quota");
1737
+ }
1738
+ function resolveCodexHealthFailurePresentation(healthCheck) {
1739
+ if (isCodexModelSelectionFailure(healthCheck)) {
1740
+ const model = healthCheck.diagnostics.model?.trim();
1741
+ return {
1742
+ reason: model
1743
+ ? `Configured Codex model is invalid or unsupported: ${model}.`
1744
+ : "Configured Codex model is invalid or unsupported.",
1745
+ fix: "Set `codex.model` to a supported model, then rerun `optimus doctor`."
1746
+ };
1747
+ }
1748
+ if (isCodexQuotaFailure(healthCheck)) {
1749
+ return {
1750
+ reason: "Codex quota is exhausted or billing is unavailable.",
1751
+ fix: "Check the configured OpenAI API key quota and billing status, then rerun `optimus doctor`."
1752
+ };
1753
+ }
1754
+ if (healthCheck.diagnostics.failureCategory === "provider_error") {
1755
+ return {
1756
+ reason: "model provider is unreachable.",
1757
+ fix: "Retry `optimus doctor` after fixing the Codex connection."
1758
+ };
1759
+ }
1760
+ if (healthCheck.diagnostics.failureCategory === "network_error") {
1761
+ return {
1762
+ reason: "network connectivity to Codex is unavailable.",
1763
+ fix: "Retry `optimus doctor` after fixing the Codex connection."
1764
+ };
1765
+ }
1766
+ if (healthCheck.diagnostics.failureCategory === "config_error") {
1767
+ return {
1768
+ reason: "Codex configuration is invalid.",
1769
+ fix: "Review `codex.model`, auth mode, and provider settings, then rerun `optimus doctor`."
1770
+ };
1771
+ }
1772
+ const authFixHint = healthCheck.diagnostics.auth?.fixHint?.trim();
1773
+ const summary = healthCheck.summary.trim().replace(/\.$/u, "");
1774
+ return {
1775
+ reason: summary || "Codex request could not complete.",
1776
+ fix: authFixHint && !healthCheck.diagnostics.auth?.authenticated
1777
+ ? authFixHint
1778
+ : "Inspect the Codex failure reason above, fix it, then rerun `optimus doctor`."
1779
+ };
1780
+ }
1711
1781
  function doctorNextActions(quick, healthCheck, delivery) {
1712
1782
  const actions = new Set();
1713
1783
  for (const step of quick.next) {
1714
1784
  actions.add(step);
1715
1785
  }
1716
1786
  if (!healthCheck.ok) {
1717
- const fixHint = healthCheck.diagnostics.auth?.fixHint?.trim();
1718
- if (fixHint) {
1719
- actions.add(fixHint);
1720
- }
1721
- else {
1722
- actions.add("Rerun `optimus setup`.");
1723
- }
1787
+ actions.add(resolveCodexHealthFailurePresentation(healthCheck).fix);
1724
1788
  }
1725
1789
  if (delivery.status === "not_ok" && delivery.fix) {
1726
1790
  actions.add(delivery.fix);
@@ -1799,6 +1863,7 @@ async function runDoctor(configPath = resolveDefaultConfigPath()) {
1799
1863
  };
1800
1864
  const authDiagnostics = healthCheck.diagnostics.auth;
1801
1865
  const codexIssue = quick.blocking.find((issue) => issue.code.startsWith("codex_"));
1866
+ const codexHealthFailure = resolveCodexHealthFailurePresentation(healthCheck);
1802
1867
  const codexAuth = authDiagnostics?.authenticated
1803
1868
  ? { status: "ok" }
1804
1869
  : {
@@ -1817,12 +1882,8 @@ async function runDoctor(configPath = resolveDefaultConfigPath()) {
1817
1882
  ? { status: "ok" }
1818
1883
  : {
1819
1884
  status: "not_ok",
1820
- reason: healthCheck.diagnostics.failureCategory === "provider_error"
1821
- ? "model provider is unreachable."
1822
- : healthCheck.diagnostics.failureCategory === "network_error"
1823
- ? "network connectivity to Codex is unavailable."
1824
- : "Codex request could not complete.",
1825
- fix: authDiagnostics.fixHint?.trim() || "Retry `optimus doctor` after fixing the Codex connection."
1885
+ reason: codexHealthFailure.reason,
1886
+ fix: codexHealthFailure.fix
1826
1887
  };
1827
1888
  const codex = healthCheck.ok
1828
1889
  ? {
@@ -1834,10 +1895,10 @@ async function runDoctor(configPath = resolveDefaultConfigPath()) {
1834
1895
  status: "not_ok",
1835
1896
  reason: summarizeIssue(codexIssue, !authDiagnostics?.authenticated
1836
1897
  ? "authentication is not usable."
1837
- : healthCheck.diagnostics.failureCategory === "provider_error"
1838
- ? "model provider is unreachable."
1839
- : "Codex is not ready."),
1840
- fix: authDiagnostics?.fixHint?.trim() || "Rerun `optimus setup`.",
1898
+ : codexHealthFailure.reason),
1899
+ fix: !authDiagnostics?.authenticated
1900
+ ? authDiagnostics?.fixHint?.trim() || "Rerun `optimus setup`."
1901
+ : codexHealthFailure.fix,
1841
1902
  auth: codexAuth,
1842
1903
  connectivity: codexConnectivity
1843
1904
  };
@@ -2166,6 +2227,44 @@ function parseArgs(argv) {
2166
2227
  function parsedCommandHasHelp(argv) {
2167
2228
  return argv.some((token) => token === "-h" || token === "--help");
2168
2229
  }
2230
+ async function readTextFromStdin() {
2231
+ const chunks = [];
2232
+ for await (const chunk of input) {
2233
+ chunks.push(typeof chunk === "string" ? chunk : chunk.toString("utf8"));
2234
+ }
2235
+ return chunks.join("");
2236
+ }
2237
+ async function resolveLongTextArg(args, keys) {
2238
+ for (const key of keys.inline) {
2239
+ const value = args[key]?.trim();
2240
+ if (value) {
2241
+ return value;
2242
+ }
2243
+ }
2244
+ const filePath = keys.file ? args[keys.file]?.trim() : undefined;
2245
+ if (filePath) {
2246
+ const content = (await readFile(filePath, "utf8")).trim();
2247
+ if (content) {
2248
+ return content;
2249
+ }
2250
+ }
2251
+ if (keys.stdin && args[keys.stdin] === "true") {
2252
+ const content = (await readTextFromStdin()).trim();
2253
+ if (content) {
2254
+ return content;
2255
+ }
2256
+ }
2257
+ return undefined;
2258
+ }
2259
+ function renderShellQuotingHint(command) {
2260
+ return [
2261
+ `${command} requires both --title and --description.`,
2262
+ "Tip: shell metacharacters like `...`, $(...), and $VAR may be expanded before Optimus starts.",
2263
+ "Use single quotes, or pass the text with --description-file / --description-stdin.",
2264
+ `Example: optimus ${command} --title "..." --description 'literal text with \`optimus setup\` inside'`,
2265
+ `Example: printf '%s' 'literal text with \`optimus setup\` inside' | optimus ${command} --title "..." --description-stdin`
2266
+ ].join("\n");
2267
+ }
2169
2268
  async function main() {
2170
2269
  const argv = process.argv.slice(2);
2171
2270
  const [firstArg, ...rest] = argv;
@@ -2356,9 +2455,13 @@ async function main() {
2356
2455
  if (command === "submit") {
2357
2456
  const args = parseArgs(commandArgs);
2358
2457
  const title = args.title?.trim();
2359
- const description = (args.desc ?? args.description)?.trim();
2458
+ const description = await resolveLongTextArg(args, {
2459
+ inline: ["desc", "description"],
2460
+ file: "description-file",
2461
+ stdin: "description-stdin"
2462
+ });
2360
2463
  if (!title || !description) {
2361
- console.error("submit requires both --title and --description");
2464
+ console.error(renderShellQuotingHint("submit"));
2362
2465
  process.exitCode = 1;
2363
2466
  return;
2364
2467
  }
@@ -2381,9 +2484,13 @@ async function main() {
2381
2484
  if (command === "feedback") {
2382
2485
  const args = parseArgs(commandArgs);
2383
2486
  const title = args.title?.trim();
2384
- const description = (args.desc ?? args.description)?.trim();
2487
+ const description = await resolveLongTextArg(args, {
2488
+ inline: ["desc", "description"],
2489
+ file: "description-file",
2490
+ stdin: "description-stdin"
2491
+ });
2385
2492
  if (!title || !description) {
2386
- console.error("feedback requires both --title and --description");
2493
+ console.error(renderShellQuotingHint("feedback"));
2387
2494
  process.exitCode = 1;
2388
2495
  return;
2389
2496
  }