agentweaver 0.1.12 → 0.1.13

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.
@@ -0,0 +1,89 @@
1
+ import { DoctorStatus, ReadinessStatus } from "./types.js";
2
+ import { REGISTRY } from "./registry.js";
3
+ import { DoctorOrchestrator } from "./orchestrator.js";
4
+ import { CATEGORY } from "./checks/category.js";
5
+ import "./checks/register.js";
6
+ const STATUS_ICONS = {
7
+ [DoctorStatus.Ok]: "✓",
8
+ [DoctorStatus.Warn]: "⚠",
9
+ [DoctorStatus.Fail]: "✗",
10
+ };
11
+ const READINESS_LABELS = {
12
+ [ReadinessStatus.Ready]: "Ready",
13
+ [ReadinessStatus.ReadyWithWarnings]: "Ready with warnings",
14
+ [ReadinessStatus.NotReady]: "Not ready",
15
+ };
16
+ const CATEGORY_LABELS = {
17
+ [CATEGORY.SYSTEM]: "System",
18
+ [CATEGORY.EXECUTORS]: "Executors",
19
+ [CATEGORY.ENV_DIAGNOSTICS]: "Environment",
20
+ [CATEGORY.FLOW_READINESS]: "Flow Readiness",
21
+ };
22
+ async function runDoctorCommand(args) {
23
+ const jsonMode = args.includes("--json");
24
+ const filter = args.find((arg) => arg !== "--json");
25
+ const orchestrator = new DoctorOrchestrator();
26
+ const report = await orchestrator.run(undefined, filter);
27
+ if (jsonMode) {
28
+ process.stdout.write(JSON.stringify(report, null, 2));
29
+ return report.overall === ReadinessStatus.NotReady ? 1 : 0;
30
+ }
31
+ const grouped = new Map();
32
+ for (const result of report.checks) {
33
+ const check = REGISTRY.getById(result.id);
34
+ const cat = check?.category ?? "unknown";
35
+ if (!grouped.has(cat)) {
36
+ grouped.set(cat, []);
37
+ }
38
+ grouped.get(cat).push(result);
39
+ }
40
+ const categoryOrder = [
41
+ CATEGORY.SYSTEM,
42
+ CATEGORY.EXECUTORS,
43
+ CATEGORY.ENV_DIAGNOSTICS,
44
+ CATEGORY.FLOW_READINESS,
45
+ ];
46
+ for (const cat of categoryOrder) {
47
+ const items = grouped.get(cat);
48
+ if (!items || items.length === 0)
49
+ continue;
50
+ const label = CATEGORY_LABELS[cat] ?? cat;
51
+ console.log(`## ${label}`);
52
+ console.log();
53
+ for (const result of items) {
54
+ const icon = STATUS_ICONS[result.status];
55
+ const line = `[${icon}] ${result.title} - ${result.message}`;
56
+ console.log(line);
57
+ if (result.hint) {
58
+ console.log(` Hint: ${result.hint}`);
59
+ }
60
+ if (result.details) {
61
+ console.log(` Details: ${result.details}`);
62
+ }
63
+ }
64
+ console.log();
65
+ }
66
+ for (const [cat, items] of grouped) {
67
+ if (categoryOrder.includes(cat))
68
+ continue;
69
+ const label = CATEGORY_LABELS[cat] ?? cat;
70
+ console.log(`## ${label}`);
71
+ console.log();
72
+ for (const result of items) {
73
+ const icon = STATUS_ICONS[result.status];
74
+ const line = `[${icon}] ${result.title} - ${result.message}`;
75
+ console.log(line);
76
+ if (result.hint) {
77
+ console.log(` Hint: ${result.hint}`);
78
+ }
79
+ if (result.details) {
80
+ console.log(` Details: ${result.details}`);
81
+ }
82
+ }
83
+ console.log();
84
+ }
85
+ console.log(`Overall: ${READINESS_LABELS[report.overall]}`);
86
+ console.log(`Timestamp: ${report.timestamp}`);
87
+ return report.overall === ReadinessStatus.NotReady ? 1 : 0;
88
+ }
89
+ export { runDoctorCommand };
@@ -0,0 +1,12 @@
1
+ export var DoctorStatus;
2
+ (function (DoctorStatus) {
3
+ DoctorStatus["Ok"] = "ok";
4
+ DoctorStatus["Warn"] = "warn";
5
+ DoctorStatus["Fail"] = "fail";
6
+ })(DoctorStatus || (DoctorStatus = {}));
7
+ export var ReadinessStatus;
8
+ (function (ReadinessStatus) {
9
+ ReadinessStatus["Ready"] = "ready";
10
+ ReadinessStatus["ReadyWithWarnings"] = "ready_with_warnings";
11
+ ReadinessStatus["NotReady"] = "not_ready";
12
+ })(ReadinessStatus || (ReadinessStatus = {}));
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ import { runCommand } from "./runtime/process-runner.js";
23
23
  import { InteractiveUi } from "./interactive-ui.js";
24
24
  import { bye, printError, printInfo, printPanel, printSummary, setFlowExecutionState, stripAnsi, } from "./tui.js";
25
25
  import { requestUserInputInTerminal } from "./user-input.js";
26
+ import { runDoctorCommand } from "./doctor/index.js";
26
27
  import { attachJiraContext, detectGitBranchName, requestJiraContext, resolveProjectScope, } from "./scope.js";
27
28
  const COMMANDS = [
28
29
  "auto-golang",
@@ -31,6 +32,7 @@ const COMMANDS = [
31
32
  "auto-reset",
32
33
  "bug-analyze",
33
34
  "bug-fix",
35
+ "doctor",
34
36
  "git-commit",
35
37
  "gitlab-diff-review",
36
38
  "gitlab-review",
@@ -97,6 +99,7 @@ function usage() {
97
99
  agentweaver gitlab-review [--dry] [--verbose] [--prompt <text>] [--scope <name>]
98
100
  agentweaver bug-analyze [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
99
101
  agentweaver bug-fix [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
102
+ agentweaver doctor [<category>|<check-id>] [--json]
100
103
  agentweaver mr-description [--dry] [--verbose] [--prompt <text>] <jira-browse-url|jira-issue-key>
101
104
  agentweaver plan [--dry] [--verbose] [--prompt <text>] [--md-lang <en|ru>] [<jira-browse-url|jira-issue-key>]
102
105
  agentweaver task-describe [--dry] [--verbose] [--prompt <text>] [<jira-browse-url|jira-issue-key>]
@@ -434,6 +437,7 @@ function buildBaseConfig(command, options = {}) {
434
437
  mdLang: options.mdLang ?? null,
435
438
  dryRun: options.dryRun ?? false,
436
439
  verbose: options.verbose ?? false,
440
+ ...(options.doctorArgs !== undefined ? { doctorArgs: options.doctorArgs } : {}),
437
441
  };
438
442
  }
439
443
  function commandRequiresTask(command) {
@@ -755,6 +759,10 @@ function requireJiraConfig(config) {
755
759
  }
756
760
  }
757
761
  async function executeCommand(baseConfig, runFollowupVerify = true, requestUserInput = requestUserInputInTerminal, resolvedScope, setSummary, forceRefreshSummary = false, launchMode = "restart", launchProfile, runtime = runtimeServices) {
762
+ if (baseConfig.command === "doctor") {
763
+ const exitCode = await runDoctorCommand(baseConfig.doctorArgs ?? []);
764
+ return exitCode === 0;
765
+ }
758
766
  const config = buildRuntimeConfig(baseConfig, resolvedScope ?? (await resolveScopeForCommand(baseConfig, requestUserInput)));
759
767
  if (config.command === "auto-golang") {
760
768
  requireJiraConfig(config);
@@ -1058,6 +1066,7 @@ function parseCliArgs(argv) {
1058
1066
  let helpPhases = false;
1059
1067
  let jiraRef;
1060
1068
  let mdLang;
1069
+ const doctorArgs = [];
1061
1070
  for (let index = 1; index < argv.length; index += 1) {
1062
1071
  const token = argv[index] ?? "";
1063
1072
  if (token === "--dry") {
@@ -1110,7 +1119,12 @@ function parseCliArgs(argv) {
1110
1119
  }
1111
1120
  continue;
1112
1121
  }
1113
- jiraRef = token;
1122
+ if (command === "doctor") {
1123
+ doctorArgs.push(token);
1124
+ }
1125
+ else {
1126
+ jiraRef = token;
1127
+ }
1114
1128
  }
1115
1129
  if (command === "auto-golang" && helpPhases) {
1116
1130
  printAutoPhasesHelp();
@@ -1130,6 +1144,7 @@ function parseCliArgs(argv) {
1130
1144
  ...(prompt !== undefined ? { prompt } : {}),
1131
1145
  ...(autoFromPhase !== undefined ? { autoFromPhase } : {}),
1132
1146
  ...(mdLang !== undefined ? { mdLang } : {}),
1147
+ ...(doctorArgs.length > 0 ? { doctorArgs } : {}),
1133
1148
  };
1134
1149
  }
1135
1150
  function buildConfigFromArgs(args) {
@@ -1141,6 +1156,7 @@ function buildConfigFromArgs(args) {
1141
1156
  ...(args.mdLang !== undefined ? { mdLang: args.mdLang } : {}),
1142
1157
  dryRun: args.dry,
1143
1158
  verbose: args.verbose,
1159
+ ...(args.doctorArgs !== undefined ? { doctorArgs: args.doctorArgs } : {}),
1144
1160
  });
1145
1161
  }
1146
1162
  async function runInteractive(jiraRef, forceRefresh = false, scopeName) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentweaver",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "CLI orchestrator for Jira/Codex engineering workflows",
5
5
  "keywords": [
6
6
  "agent",
@@ -50,11 +50,13 @@
50
50
  },
51
51
  "devDependencies": {
52
52
  "@types/node": "^20.17.30",
53
+ "@types/semver": "^7.7.1",
53
54
  "ts-node": "^10.9.2",
54
55
  "typescript": "^5.8.3"
55
56
  },
56
57
  "dependencies": {
57
58
  "markdown-it": "^14.1.1",
58
- "neo-blessed": "^0.2.0"
59
+ "neo-blessed": "^0.2.0",
60
+ "semver": "^7.7.4"
59
61
  }
60
62
  }
@@ -1,77 +0,0 @@
1
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
- import path from "node:path";
3
- import { DEFAULT_MODEL_BY_EXECUTOR, defaultModelForExecutor } from "./launch-profile-config.js";
4
- import { scopeArtifactsDir } from "../artifacts.js";
5
- const FLOW_MODEL_SETTINGS_FILE = "agentweaver-flow-model-settings.json";
6
- function flowModelSettingsPath(scopeKey) {
7
- return path.join(scopeArtifactsDir(scopeKey), FLOW_MODEL_SETTINGS_FILE);
8
- }
9
- function ensureArtifactsDir(scopeKey) {
10
- const artifactsDir = scopeArtifactsDir(scopeKey);
11
- if (!existsSync(artifactsDir)) {
12
- mkdirSync(artifactsDir, { recursive: true });
13
- }
14
- }
15
- export function loadFlowModelSettings(scopeKey) {
16
- const filePath = flowModelSettingsPath(scopeKey);
17
- if (!existsSync(filePath)) {
18
- return {};
19
- }
20
- try {
21
- const content = readFileSync(filePath, "utf8");
22
- const parsed = JSON.parse(content);
23
- if (typeof parsed !== "object" || parsed === null) {
24
- return {};
25
- }
26
- return parsed;
27
- }
28
- catch {
29
- return {};
30
- }
31
- }
32
- export function saveFlowModelSettings(scopeKey, store) {
33
- ensureArtifactsDir(scopeKey);
34
- const filePath = flowModelSettingsPath(scopeKey);
35
- const tempPath = `${filePath}.tmp`;
36
- const content = JSON.stringify(store, null, 2);
37
- writeFileSync(tempPath, content, "utf8");
38
- renameSync(tempPath, filePath);
39
- }
40
- export function getEffectiveModelForFlow(flowId, scopeKey, executor) {
41
- const store = loadFlowModelSettings(scopeKey);
42
- const flowSettings = store[flowId];
43
- if (!flowSettings) {
44
- return defaultModelForExecutor(executor);
45
- }
46
- if (flowSettings.lastSelectedModel && flowSettings.lastSelectedModel !== "default") {
47
- return flowSettings.lastSelectedModel;
48
- }
49
- if (flowSettings.defaultModel && flowSettings.defaultModel !== "default") {
50
- return flowSettings.defaultModel;
51
- }
52
- return defaultModelForExecutor(executor);
53
- }
54
- export function updateLastSelectedModel(flowId, scopeKey, executor, model) {
55
- const store = loadFlowModelSettings(scopeKey);
56
- const existingSettings = store[flowId];
57
- if (existingSettings) {
58
- store[flowId] = {
59
- ...existingSettings,
60
- executor,
61
- defaultModel: model,
62
- lastSelectedModel: model,
63
- };
64
- }
65
- else {
66
- store[flowId] = {
67
- executor,
68
- defaultModel: DEFAULT_MODEL_BY_EXECUTOR[executor],
69
- lastSelectedModel: model,
70
- };
71
- }
72
- saveFlowModelSettings(scopeKey, store);
73
- }
74
- export function getFlowModelSettings(flowId, scopeKey) {
75
- const store = loadFlowModelSettings(scopeKey);
76
- return store[flowId] ?? null;
77
- }