@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.
- package/README.md +3 -0
- package/dist/cli/optimus.js +130 -23
- package/dist/cli/optimus.js.map +1 -1
- package/dist/config/load-config.js +2 -1
- package/dist/config/load-config.js.map +1 -1
- package/dist/integrations/jira/jira-access-manager.d.ts +34 -0
- package/dist/integrations/jira/jira-access-manager.js +140 -0
- package/dist/integrations/jira/jira-access-manager.js.map +1 -0
- package/dist/integrations/jira/jira-cli.js +13 -23
- package/dist/integrations/jira/jira-cli.js.map +1 -1
- package/dist/integrations/jira/jira-client.js +2 -0
- package/dist/integrations/jira/jira-client.js.map +1 -1
- package/dist/integrations/jira/jira-submit.d.ts +2 -1
- package/dist/integrations/jira/jira-submit.js +15 -14
- package/dist/integrations/jira/jira-submit.js.map +1 -1
- package/dist/problem-solving-core/codex/codex-failure-classifier.js +11 -2
- package/dist/problem-solving-core/codex/codex-failure-classifier.js.map +1 -1
- package/dist/task-environment/delivery/task-publication-service.d.ts +1 -0
- package/dist/task-environment/delivery/task-publication-service.js +52 -44
- package/dist/task-environment/delivery/task-publication-service.js.map +1 -1
- package/dist/task-environment/intake/triage-rejection-feedback-service.d.ts +0 -1
- package/dist/task-environment/intake/triage-rejection-feedback-service.js +38 -32
- package/dist/task-environment/intake/triage-rejection-feedback-service.js.map +1 -1
- package/dist/task-environment/orchestration/task-orchestrator.js +1 -1
- package/dist/task-environment/orchestration/triage-runner.d.ts +1 -0
- package/dist/task-environment/orchestration/triage-runner.js +10 -2
- package/dist/task-environment/orchestration/triage-runner.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/embedded-skills/task/bugfix/android-debug-protocol/SKILL.md +10 -0
- package/embedded-skills/task/bugfix/android-debug-protocol/skill.json +6 -0
- package/optimus.config.template.json +1 -1
- 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
|
package/dist/cli/optimus.js
CHANGED
|
@@ -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
|
-
" --
|
|
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
|
-
|
|
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:
|
|
1821
|
-
|
|
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
|
-
:
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
2493
|
+
console.error(renderShellQuotingHint("feedback"));
|
|
2387
2494
|
process.exitCode = 1;
|
|
2388
2495
|
return;
|
|
2389
2496
|
}
|