agent-detective 1.0.0
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/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/chunk-H2IXGHNA.js +1237 -0
- package/dist/chunk-OIYJYLCB.js +685 -0
- package/dist/doctor-3ZMDZLW6.js +193 -0
- package/dist/index.js +661 -0
- package/dist/init-IPCDLNHA.js +179 -0
- package/package.json +88 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
isKnownAgent,
|
|
4
|
+
loadConfig,
|
|
5
|
+
normalizeAgent
|
|
6
|
+
} from "./chunk-H2IXGHNA.js";
|
|
7
|
+
|
|
8
|
+
// src/cli/init.ts
|
|
9
|
+
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
10
|
+
import { basename, isAbsolute, resolve } from "path";
|
|
11
|
+
function resolveConfigDirFromInstallRoot(installRoot) {
|
|
12
|
+
if (installRoot && installRoot.split(/[\\/]/).pop() === "config") {
|
|
13
|
+
return installRoot;
|
|
14
|
+
}
|
|
15
|
+
const base = installRoot ?? process.cwd();
|
|
16
|
+
return resolve(base, "config");
|
|
17
|
+
}
|
|
18
|
+
function takeFlagValue(args, flag) {
|
|
19
|
+
for (let i = 0; i < args.length; i++) {
|
|
20
|
+
const a = args[i];
|
|
21
|
+
if (a === flag) return args[i + 1];
|
|
22
|
+
if (a?.startsWith(`${flag}=`)) return a.slice(flag.length + 1);
|
|
23
|
+
}
|
|
24
|
+
return void 0;
|
|
25
|
+
}
|
|
26
|
+
function parseInitFlags(argv) {
|
|
27
|
+
const args = argv.slice(2).filter((a) => a !== "init");
|
|
28
|
+
const repoPath = takeFlagValue(args, "--repo-path") ?? process.cwd();
|
|
29
|
+
const repoName = takeFlagValue(args, "--repo-name") ?? (basename(repoPath) || "symfony");
|
|
30
|
+
const agentRaw = takeFlagValue(args, "--agent") ?? "opencode";
|
|
31
|
+
const agent = isKnownAgent(agentRaw) ? normalizeAgent(agentRaw) : normalizeAgent("opencode");
|
|
32
|
+
return {
|
|
33
|
+
repoPath,
|
|
34
|
+
repoName,
|
|
35
|
+
agent,
|
|
36
|
+
force: args.includes("--force"),
|
|
37
|
+
json: args.includes("--json")
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function buildInitLocalConfig(options) {
|
|
41
|
+
const repoPath = isAbsolute(options.repoPath) ? options.repoPath : resolve(process.cwd(), options.repoPath);
|
|
42
|
+
return {
|
|
43
|
+
port: 3001,
|
|
44
|
+
agent: options.agent,
|
|
45
|
+
agents: {
|
|
46
|
+
[options.agent]: { defaultModel: defaultModelForAgent(options.agent) }
|
|
47
|
+
},
|
|
48
|
+
plugins: [
|
|
49
|
+
{
|
|
50
|
+
package: "@agent-detective/local-repos-plugin",
|
|
51
|
+
options: {
|
|
52
|
+
repos: [
|
|
53
|
+
{
|
|
54
|
+
name: options.repoName,
|
|
55
|
+
path: repoPath,
|
|
56
|
+
description: `Repo matched when Jira issue has label ${options.repoName}`
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
validation: { failOnMissing: false }
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
package: "@agent-detective/jira-adapter",
|
|
64
|
+
options: {
|
|
65
|
+
enabled: true,
|
|
66
|
+
mockMode: true,
|
|
67
|
+
webhookBehavior: {
|
|
68
|
+
defaults: {
|
|
69
|
+
action: "ignore",
|
|
70
|
+
acknowledgmentMessage: "Thanks \u2014 we are reviewing this issue."
|
|
71
|
+
},
|
|
72
|
+
events: {
|
|
73
|
+
"jira:issue_created": { action: "analyze" },
|
|
74
|
+
"jira:comment_created": { action: "analyze" }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
package: "@agent-detective/linear-adapter",
|
|
81
|
+
options: { enabled: false, mockMode: true }
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
package: "@agent-detective/pr-pipeline",
|
|
85
|
+
options: {
|
|
86
|
+
prBranchPrefix: "hotfix/",
|
|
87
|
+
prTitleTemplate: "[{{key}}] {{summary}}",
|
|
88
|
+
prDryRun: true
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function defaultModelForAgent(agentId) {
|
|
95
|
+
switch (agentId) {
|
|
96
|
+
case "claude":
|
|
97
|
+
return "sonnet";
|
|
98
|
+
case "cursor":
|
|
99
|
+
return "composer-2.5-fast";
|
|
100
|
+
default:
|
|
101
|
+
return "opencode/deepseek-v4-flash-free";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function printNextSteps(installRoot, repoName) {
|
|
105
|
+
const rootFlag = installRoot !== process.cwd() ? ` --config-root ${installRoot}` : "";
|
|
106
|
+
console.log(`
|
|
107
|
+
Created config/local.json (mockMode: true).
|
|
108
|
+
|
|
109
|
+
Next steps:
|
|
110
|
+
1. agent-detective doctor${rootFlag}
|
|
111
|
+
2. agent-detective${rootFlag}
|
|
112
|
+
|
|
113
|
+
Mock webhook smoke (server running in another terminal):
|
|
114
|
+
From a git clone: pnpm run jira:webhook-smoke
|
|
115
|
+
Bundled fixture labels: probando, symfony \u2014 your repo name is "${repoName}".
|
|
116
|
+
For a match with the fixture, re-run init with --repo-name symfony or add label "${repoName}" in Jira.
|
|
117
|
+
|
|
118
|
+
Logs should show [MOCK] Added comment when mock analysis completes.
|
|
119
|
+
`);
|
|
120
|
+
}
|
|
121
|
+
async function runInit({ installRoot, argv }) {
|
|
122
|
+
const flags = parseInitFlags(argv);
|
|
123
|
+
const configDir = resolveConfigDirFromInstallRoot(installRoot);
|
|
124
|
+
const localPath = resolve(configDir, "local.json");
|
|
125
|
+
const installRootUsed = installRoot ?? process.cwd();
|
|
126
|
+
if (existsSync(localPath) && !flags.force) {
|
|
127
|
+
const message = `Refusing to overwrite ${localPath}. Use --force to replace it.`;
|
|
128
|
+
if (flags.json) {
|
|
129
|
+
console.log(JSON.stringify({ ok: false, error: message, localPath }, null, 2));
|
|
130
|
+
} else {
|
|
131
|
+
console.error(message);
|
|
132
|
+
}
|
|
133
|
+
process.exitCode = 1;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
mkdirSync(configDir, { recursive: true });
|
|
137
|
+
const config = buildInitLocalConfig(flags);
|
|
138
|
+
writeFileSync(localPath, `${JSON.stringify(config, null, 2)}
|
|
139
|
+
`, "utf8");
|
|
140
|
+
let validated = true;
|
|
141
|
+
let validationError;
|
|
142
|
+
try {
|
|
143
|
+
loadConfig({ configRoot: configDir });
|
|
144
|
+
} catch (err) {
|
|
145
|
+
validated = false;
|
|
146
|
+
validationError = err.message;
|
|
147
|
+
}
|
|
148
|
+
if (flags.json) {
|
|
149
|
+
console.log(
|
|
150
|
+
JSON.stringify(
|
|
151
|
+
{
|
|
152
|
+
ok: validated,
|
|
153
|
+
localPath,
|
|
154
|
+
configDir,
|
|
155
|
+
installRootUsed,
|
|
156
|
+
repoName: flags.repoName,
|
|
157
|
+
repoPath: flags.repoPath,
|
|
158
|
+
agent: flags.agent,
|
|
159
|
+
validationError
|
|
160
|
+
},
|
|
161
|
+
null,
|
|
162
|
+
2
|
|
163
|
+
)
|
|
164
|
+
);
|
|
165
|
+
} else {
|
|
166
|
+
console.log(`Wrote ${localPath}`);
|
|
167
|
+
if (!validated) {
|
|
168
|
+
console.error(`Warning: generated config failed validation: ${validationError}`);
|
|
169
|
+
} else {
|
|
170
|
+
printNextSteps(installRootUsed, flags.repoName);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
process.exitCode = validated ? 0 : 1;
|
|
174
|
+
}
|
|
175
|
+
export {
|
|
176
|
+
buildInitLocalConfig,
|
|
177
|
+
parseInitFlags,
|
|
178
|
+
runInit
|
|
179
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-detective",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "AI-powered code analysis agent that responds to events from Jira, Telegram, Slack and more",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"agent-detective": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"code-analysis",
|
|
19
|
+
"agent"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"jira.js": "^5.3.1",
|
|
24
|
+
"@fastify/swagger": "^9.7.0",
|
|
25
|
+
"@scalar/fastify-api-reference": "^1.57.5",
|
|
26
|
+
"fastify": "^5.8.5",
|
|
27
|
+
"fastify-type-provider-zod": "^6.1.0",
|
|
28
|
+
"openapi-types": "^12.1.3",
|
|
29
|
+
"zod": "^4.4.3",
|
|
30
|
+
"@agent-detective/jira-adapter": "1.0.0",
|
|
31
|
+
"@agent-detective/linear-adapter": "1.0.0",
|
|
32
|
+
"@agent-detective/observability": "1.0.0",
|
|
33
|
+
"@agent-detective/pr-pipeline": "1.0.0",
|
|
34
|
+
"@agent-detective/sdk": "1.0.0",
|
|
35
|
+
"@agent-detective/types": "1.0.0",
|
|
36
|
+
"@agent-detective/process-utils": "1.0.0",
|
|
37
|
+
"@agent-detective/local-repos-plugin": "1.0.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@commitlint/cli": "^20.4.0",
|
|
41
|
+
"@commitlint/config-conventional": "^20.4.0",
|
|
42
|
+
"@eslint/js": "^10.0.1",
|
|
43
|
+
"husky": "^9.1.7",
|
|
44
|
+
"@types/node": "^25.9.1",
|
|
45
|
+
"eslint": "^10.4.0",
|
|
46
|
+
"tmp": "^0.2.7",
|
|
47
|
+
"tsup": "^8.5.1",
|
|
48
|
+
"tsx": "^4.22.3",
|
|
49
|
+
"turbo": "^2.9.16",
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
|
+
"typescript-eslint": "^8.60.0"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=24.0.0"
|
|
55
|
+
},
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/andezdev/agent-detective.git"
|
|
59
|
+
},
|
|
60
|
+
"author": "Antonio Hernandez",
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/andezdev/agent-detective/issues"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"postinstall": "node scripts/sync-cursor-from-agents.mjs",
|
|
66
|
+
"agents:sync-cursor": "node scripts/sync-cursor-from-agents.mjs",
|
|
67
|
+
"dev": "tsx watch src/index.ts",
|
|
68
|
+
"build": "turbo run build",
|
|
69
|
+
"build:app": "tsup --config tsup.config.ts",
|
|
70
|
+
"build:types": "pnpm --filter @agent-detective/types build",
|
|
71
|
+
"typecheck": "turbo run typecheck && tsc --noEmit",
|
|
72
|
+
"lint": "turbo run lint && node scripts/check-package-root-imports.mjs && node scripts/check-plugin-cross-imports.mjs && node scripts/check-docs-internal-links.mjs",
|
|
73
|
+
"test": "turbo run test && tsx --test 'test/**/*.test.ts'",
|
|
74
|
+
"test:watch": "tsx --test --watch 'test/**/*.test.ts'",
|
|
75
|
+
"docs:plugins": "tsx scripts/generate-plugin-config-docs.ts",
|
|
76
|
+
"docs:plugins:check": "pnpm docs:plugins && git diff --exit-code docs/reference/generated/plugin-options.md",
|
|
77
|
+
"docs:config": "tsx scripts/generate-app-config-doc.ts",
|
|
78
|
+
"docs:config:check": "pnpm docs:config && git diff --exit-code docs/reference/generated/app-config.md",
|
|
79
|
+
"docs:site:sync": "node scripts/sync-starlight-content.mjs",
|
|
80
|
+
"docs:site": "pnpm --filter agent-detective-docs build",
|
|
81
|
+
"docs:site:landing": "pnpm --filter agent-detective-docs build && pnpm --filter agent-detective-landing build && node scripts/merge-landing-into-docs-dist.mjs",
|
|
82
|
+
"docs:site:dev": "pnpm --filter agent-detective-docs dev",
|
|
83
|
+
"landing:dev": "pnpm --filter agent-detective-landing dev",
|
|
84
|
+
"clean": "turbo run clean",
|
|
85
|
+
"start": "node dist/index.js",
|
|
86
|
+
"jira:webhook-smoke": "node scripts/jira-webhook-smoke.mjs"
|
|
87
|
+
}
|
|
88
|
+
}
|