@shepai/cli 1.151.1 → 1.151.2-pr438.6135e39
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/apis/json-schema/AgentRunDetail.yaml +28 -0
- package/apis/json-schema/DoctorDiagnosticReport.yaml +76 -0
- package/apis/json-schema/FailedRunSummary.yaml +22 -0
- package/apis/json-schema/SystemInfo.yaml +22 -0
- package/apis/json-schema/WorkerLogEntry.yaml +27 -0
- package/apis/json-schema/WorkflowConfig.yaml +5 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts +28 -0
- package/dist/packages/core/src/application/ports/output/services/git-pr-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/github-issue-service.interface.d.ts +57 -0
- package/dist/packages/core/src/application/ports/output/services/github-issue-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/github-issue-service.interface.js +39 -0
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts +37 -0
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/github-repository-service.interface.js +12 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +5 -3
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/index.js +2 -1
- package/dist/packages/core/src/application/use-cases/doctor/doctor-diagnose.use-case.d.ts +64 -0
- package/dist/packages/core/src/application/use-cases/doctor/doctor-diagnose.use-case.d.ts.map +1 -0
- package/dist/packages/core/src/application/use-cases/doctor/doctor-diagnose.use-case.js +493 -0
- package/dist/packages/core/src/domain/generated/output.d.ts +185 -0
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +4 -0
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.js +8 -2
- package/dist/packages/core/src/infrastructure/services/external/github-issue-creator.service.d.ts +17 -0
- package/dist/packages/core/src/infrastructure/services/external/github-issue-creator.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/external/github-issue-creator.service.js +69 -0
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts +3 -1
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.js +37 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +21 -0
- package/dist/src/presentation/cli/commands/doctor.command.d.ts +20 -0
- package/dist/src/presentation/cli/commands/doctor.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/doctor.command.js +129 -0
- package/dist/src/presentation/cli/index.js +2 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +28 -28
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +29 -29
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +29 -29
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +36 -36
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +26 -26
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__c6e32a23._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0b150ddf._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2138fa7e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__29580090._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c094882b._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d48c5b11._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__dac5dbf1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fae8b355._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_0c473fef._.js +2 -2
- package/web/.next/server/chunks/ssr/_0c473fef._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_1b719e7f._.js +1 -1
- package/web/.next/server/chunks/ssr/_1b719e7f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_37e8548b._.js +1 -1
- package/web/.next/server/chunks/ssr/_37e8548b._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_55d763e2._.js +1 -1
- package/web/.next/server/chunks/ssr/_55d763e2._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_6256a985._.js +1 -1
- package/web/.next/server/chunks/ssr/_6256a985._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_8fcc39d4._.js +1 -1
- package/web/.next/server/chunks/ssr/_b71645b4._.js +1 -1
- package/web/.next/server/chunks/ssr/_b71645b4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_2a9037e8._.js → _c2ca0f1b._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_2a9037e8._.js.map → _c2ca0f1b._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_d4b20e29._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
- package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_dc9a9d32._.js +3 -0
- package/web/.next/server/chunks/ssr/{_5b5dbf5b._.js.map → _dc9a9d32._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_e9e9ed20._.js +2 -2
- package/web/.next/server/chunks/ssr/_e9e9ed20._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_1be4a9a5._.js → src_presentation_web_aa941041._.js} +2 -2
- package/web/.next/server/chunks/ssr/{src_presentation_web_1be4a9a5._.js.map → src_presentation_web_aa941041._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +45 -45
- package/web/.next/static/chunks/{b113da1fbdb83ffa.js → 091de81012e2bc48.js} +1 -1
- package/web/.next/static/chunks/{c28ae41d01ad3130.js → 25889ca8401d1bc0.js} +1 -1
- package/web/.next/static/chunks/{176b3e6837dce4ad.js → 359b2815c5ed39cc.js} +1 -1
- package/web/.next/static/chunks/{fdd703b4cec873bb.js → 4a28fd1bca225386.js} +1 -1
- package/web/.next/static/chunks/{56f68c783c480176.js → 5e1877d1f1bcfd77.js} +1 -1
- package/web/.next/static/chunks/{2dfeeccc2f180ab8.js → 76a3f345f8cf2608.js} +1 -1
- package/web/.next/static/chunks/{1dc8d2933f22de05.js → 79eae02d0342fb73.js} +1 -1
- package/web/.next/static/chunks/{db5dc8b848e7ddd1.js → 80915095cec414bf.js} +1 -1
- package/web/.next/static/chunks/{067e63e1f8a471c7.js → 87b72b8a10f8255b.js} +2 -2
- package/web/.next/static/chunks/{768e2db272a413cc.js → c2388f8bc58b2a21.js} +1 -1
- package/web/.next/static/chunks/e760b952ba1a10d4.js +1 -0
- package/web/.next/static/chunks/{e860f0c546deeabc.js → ed9408f100149c34.js} +1 -1
- package/web/.next/server/chunks/ssr/_5b5dbf5b._.js +0 -3
- package/web/.next/static/chunks/b02205ef744953bc.js +0 -1
- /package/web/.next/static/{qifXEaEcnY1cbH8eHlEIN → -o7QIcv1p5C722dwF4EFd}/_buildManifest.js +0 -0
- /package/web/.next/static/{qifXEaEcnY1cbH8eHlEIN → -o7QIcv1p5C722dwF4EFd}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{qifXEaEcnY1cbH8eHlEIN → -o7QIcv1p5C722dwF4EFd}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Diagnose Use Case
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the shep doctor workflow:
|
|
5
|
+
* 1. Collect diagnostic context (failed agent runs, version, system info)
|
|
6
|
+
* 2. Create a structured GitHub issue on shep-ai/cli
|
|
7
|
+
* 3. Optionally attempt a fix via AI agent
|
|
8
|
+
* 4. Open a PR with the fix (direct push for maintainers, fork for contributors)
|
|
9
|
+
*
|
|
10
|
+
* Following Clean Architecture: all external operations are injected via interfaces.
|
|
11
|
+
*/
|
|
12
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
13
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
14
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
15
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
16
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
17
|
+
};
|
|
18
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
19
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
20
|
+
};
|
|
21
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
22
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
23
|
+
};
|
|
24
|
+
import { injectable, inject } from 'tsyringe';
|
|
25
|
+
import { randomUUID } from 'node:crypto';
|
|
26
|
+
import { tmpdir, homedir } from 'node:os';
|
|
27
|
+
import { mkdir, rm, readFile } from 'node:fs/promises';
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
import { AgentRunStatus } from '../../../domain/generated/output.js';
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Constants
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
const SHEP_REPO = 'shep-ai/cli';
|
|
34
|
+
const MAX_FAILED_RUNS = 10;
|
|
35
|
+
const ISSUE_LABELS = ['bug', 'shep-doctor'];
|
|
36
|
+
const MAX_AGENT_RUN_DETAILS = 10;
|
|
37
|
+
const MAX_WORKER_LOG_CHARS = 50_000;
|
|
38
|
+
const MAX_PROMPT_CHARS = 10_000;
|
|
39
|
+
const MAX_RESULT_CHARS = 10_000;
|
|
40
|
+
const MAX_CONVERSATION_CHARS = 20_000;
|
|
41
|
+
const MAX_PLAN_CHARS = 20_000;
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Use Case
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
let DoctorDiagnoseUseCase = class DoctorDiagnoseUseCase {
|
|
46
|
+
agentRunRepo;
|
|
47
|
+
versionService;
|
|
48
|
+
issueService;
|
|
49
|
+
repoService;
|
|
50
|
+
prService;
|
|
51
|
+
agentExecutorProvider;
|
|
52
|
+
execFile;
|
|
53
|
+
featureRepo;
|
|
54
|
+
phaseTimingRepo;
|
|
55
|
+
constructor(agentRunRepo, versionService, issueService, repoService, prService, agentExecutorProvider, execFile, featureRepo, phaseTimingRepo) {
|
|
56
|
+
this.agentRunRepo = agentRunRepo;
|
|
57
|
+
this.versionService = versionService;
|
|
58
|
+
this.issueService = issueService;
|
|
59
|
+
this.repoService = repoService;
|
|
60
|
+
this.prService = prService;
|
|
61
|
+
this.agentExecutorProvider = agentExecutorProvider;
|
|
62
|
+
this.execFile = execFile;
|
|
63
|
+
this.featureRepo = featureRepo;
|
|
64
|
+
this.phaseTimingRepo = phaseTimingRepo;
|
|
65
|
+
}
|
|
66
|
+
async execute(input) {
|
|
67
|
+
// Step 1: Collect diagnostics
|
|
68
|
+
const diagnosticReport = await this.collectDiagnostics(input.description, input.featureId);
|
|
69
|
+
// Step 2: Create GitHub issue
|
|
70
|
+
const issueTitle = this.formatIssueTitle(input.description);
|
|
71
|
+
const issueBody = this.formatIssueBody(diagnosticReport);
|
|
72
|
+
const { url: issueUrl, number: issueNumber } = await this.issueService.createIssue(SHEP_REPO, issueTitle, issueBody, ISSUE_LABELS);
|
|
73
|
+
// Step 3: If no fix requested, return early
|
|
74
|
+
if (!input.fix) {
|
|
75
|
+
return {
|
|
76
|
+
diagnosticReport,
|
|
77
|
+
issueUrl,
|
|
78
|
+
issueNumber,
|
|
79
|
+
cleanedUp: false,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Step 4: Attempt fix
|
|
83
|
+
return this.attemptFix(input, diagnosticReport, issueUrl, issueNumber);
|
|
84
|
+
}
|
|
85
|
+
// -------------------------------------------------------------------------
|
|
86
|
+
// Diagnostic Collection (Task 10)
|
|
87
|
+
// -------------------------------------------------------------------------
|
|
88
|
+
async collectDiagnostics(userDescription, featureId) {
|
|
89
|
+
let resolvedFeatureId;
|
|
90
|
+
let featureName;
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
92
|
+
let feature;
|
|
93
|
+
if (featureId) {
|
|
94
|
+
feature =
|
|
95
|
+
(await this.featureRepo.findById(featureId)) ??
|
|
96
|
+
(await this.featureRepo.findByIdPrefix(featureId));
|
|
97
|
+
if (feature) {
|
|
98
|
+
resolvedFeatureId = feature.id;
|
|
99
|
+
featureName = feature.name;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Fetch all runs once — used for both failed summaries and enrichment
|
|
103
|
+
const allRuns = await this.agentRunRepo.list();
|
|
104
|
+
const [failedRunSummaries, systemInfo, cliVersion] = await Promise.all([
|
|
105
|
+
Promise.resolve(this.filterFailedRuns(allRuns, resolvedFeatureId)),
|
|
106
|
+
this.collectSystemInfo(),
|
|
107
|
+
Promise.resolve(this.versionService.getVersion().version),
|
|
108
|
+
]);
|
|
109
|
+
const report = {
|
|
110
|
+
userDescription,
|
|
111
|
+
failedRunSummaries,
|
|
112
|
+
systemInfo,
|
|
113
|
+
cliVersion,
|
|
114
|
+
featureId: resolvedFeatureId,
|
|
115
|
+
featureName,
|
|
116
|
+
};
|
|
117
|
+
// Enrich with feature-scoped data when a feature is resolved
|
|
118
|
+
if (feature) {
|
|
119
|
+
report.featureLifecycle = feature.lifecycle;
|
|
120
|
+
report.featureBranch = feature.branch;
|
|
121
|
+
report.featureDescription = feature.description;
|
|
122
|
+
report.featureWorkflowConfig = JSON.stringify({
|
|
123
|
+
fast: feature.fast,
|
|
124
|
+
push: feature.push,
|
|
125
|
+
openPr: feature.openPr,
|
|
126
|
+
approvalGates: feature.approvalGates,
|
|
127
|
+
});
|
|
128
|
+
if (feature.messages?.length) {
|
|
129
|
+
const serialized = JSON.stringify(feature.messages);
|
|
130
|
+
report.conversationMessages = this.truncate(serialized, MAX_CONVERSATION_CHARS).text;
|
|
131
|
+
}
|
|
132
|
+
if (feature.plan) {
|
|
133
|
+
const serialized = JSON.stringify(feature.plan);
|
|
134
|
+
report.featurePlan = this.truncate(serialized, MAX_PLAN_CHARS).text;
|
|
135
|
+
}
|
|
136
|
+
// Parallel async enrichments
|
|
137
|
+
const featureRuns = allRuns.filter((r) => r.featureId === resolvedFeatureId);
|
|
138
|
+
const [specYamls, workerLogs, phaseTimings] = await Promise.all([
|
|
139
|
+
this.collectSpecYamls(feature.specPath),
|
|
140
|
+
this.collectWorkerLogs(featureRuns),
|
|
141
|
+
this.collectPhaseTimings(resolvedFeatureId),
|
|
142
|
+
]);
|
|
143
|
+
Object.assign(report, specYamls);
|
|
144
|
+
report.workerLogs = workerLogs.length > 0 ? workerLogs : undefined;
|
|
145
|
+
report.phaseTimings = phaseTimings;
|
|
146
|
+
report.agentRunDetails = this.buildAgentRunDetails(featureRuns);
|
|
147
|
+
}
|
|
148
|
+
return report;
|
|
149
|
+
}
|
|
150
|
+
filterFailedRuns(allRuns, featureId) {
|
|
151
|
+
let filtered = allRuns.filter((run) => run.status === AgentRunStatus.failed);
|
|
152
|
+
if (featureId) {
|
|
153
|
+
filtered = filtered.filter((run) => run.featureId === featureId);
|
|
154
|
+
}
|
|
155
|
+
return filtered.slice(0, MAX_FAILED_RUNS).map((run) => this.sanitizeRunSummary(run));
|
|
156
|
+
}
|
|
157
|
+
sanitizeRunSummary(run) {
|
|
158
|
+
return {
|
|
159
|
+
agentType: run.agentType,
|
|
160
|
+
agentName: run.agentName,
|
|
161
|
+
error: run.error ?? 'Unknown error',
|
|
162
|
+
timestamp: run.createdAt instanceof Date ? run.createdAt.toISOString() : String(run.createdAt),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async collectSystemInfo() {
|
|
166
|
+
let ghVersion = 'unknown';
|
|
167
|
+
try {
|
|
168
|
+
const { stdout } = await this.execFile('gh', ['--version']);
|
|
169
|
+
ghVersion = stdout.trim();
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// gh not installed or not available — use fallback
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
nodeVersion: process.version,
|
|
176
|
+
platform: process.platform,
|
|
177
|
+
arch: process.arch,
|
|
178
|
+
ghVersion,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// -------------------------------------------------------------------------
|
|
182
|
+
// Enrichment helpers
|
|
183
|
+
// -------------------------------------------------------------------------
|
|
184
|
+
truncate(content, maxChars) {
|
|
185
|
+
if (content.length <= maxChars) {
|
|
186
|
+
return { text: content, truncated: false };
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
text: `${content.slice(0, maxChars)}\n... [truncated, ${content.length} chars total]`,
|
|
190
|
+
truncated: true,
|
|
191
|
+
originalLength: content.length,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
async collectSpecYamls(specPath) {
|
|
195
|
+
if (!specPath)
|
|
196
|
+
return {};
|
|
197
|
+
const files = [
|
|
198
|
+
'spec.yaml',
|
|
199
|
+
'research.yaml',
|
|
200
|
+
'plan.yaml',
|
|
201
|
+
'tasks.yaml',
|
|
202
|
+
'feature.yaml',
|
|
203
|
+
];
|
|
204
|
+
const keys = [
|
|
205
|
+
'specYaml',
|
|
206
|
+
'researchYaml',
|
|
207
|
+
'planYaml',
|
|
208
|
+
'tasksYaml',
|
|
209
|
+
'featureStatusYaml',
|
|
210
|
+
];
|
|
211
|
+
const results = {};
|
|
212
|
+
const reads = await Promise.all(files.map((f) => this.readFileSafe(path.join(specPath, f))));
|
|
213
|
+
for (let i = 0; i < files.length; i++) {
|
|
214
|
+
if (reads[i]) {
|
|
215
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
216
|
+
results[keys[i]] = reads[i];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return results;
|
|
220
|
+
}
|
|
221
|
+
async collectWorkerLogs(featureRuns) {
|
|
222
|
+
const logDir = path.join(homedir(), '.shep', 'logs');
|
|
223
|
+
const entries = [];
|
|
224
|
+
for (const run of featureRuns) {
|
|
225
|
+
const logPath = path.join(logDir, `worker-${run.id}.log`);
|
|
226
|
+
const content = await this.readFileSafe(logPath);
|
|
227
|
+
if (content) {
|
|
228
|
+
const { text, truncated, originalLength } = this.truncate(content, MAX_WORKER_LOG_CHARS);
|
|
229
|
+
entries.push({
|
|
230
|
+
agentRunId: run.id,
|
|
231
|
+
agentName: run.agentName,
|
|
232
|
+
content: text,
|
|
233
|
+
truncated,
|
|
234
|
+
originalLength,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return entries;
|
|
239
|
+
}
|
|
240
|
+
async collectPhaseTimings(featureId) {
|
|
241
|
+
try {
|
|
242
|
+
const timings = await this.phaseTimingRepo.findByFeatureId(featureId);
|
|
243
|
+
return timings.length > 0 ? JSON.stringify(timings) : undefined;
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return undefined;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
buildAgentRunDetails(featureRuns) {
|
|
250
|
+
if (featureRuns.length === 0)
|
|
251
|
+
return undefined;
|
|
252
|
+
return featureRuns.slice(0, MAX_AGENT_RUN_DETAILS).map((run) => ({
|
|
253
|
+
agentType: run.agentType,
|
|
254
|
+
agentName: run.agentName,
|
|
255
|
+
prompt: this.truncate(run.prompt, MAX_PROMPT_CHARS).text,
|
|
256
|
+
result: run.result ? this.truncate(run.result, MAX_RESULT_CHARS).text : undefined,
|
|
257
|
+
error: run.error ?? undefined,
|
|
258
|
+
timestamp: run.createdAt instanceof Date ? run.createdAt.toISOString() : String(run.createdAt),
|
|
259
|
+
}));
|
|
260
|
+
}
|
|
261
|
+
async readFileSafe(filePath) {
|
|
262
|
+
try {
|
|
263
|
+
return await readFile(filePath, 'utf-8');
|
|
264
|
+
}
|
|
265
|
+
catch {
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// -------------------------------------------------------------------------
|
|
270
|
+
// Issue Formatting (Task 11)
|
|
271
|
+
// -------------------------------------------------------------------------
|
|
272
|
+
formatIssueTitle(description) {
|
|
273
|
+
const firstLine = description.split('\n')[0].trim();
|
|
274
|
+
const truncated = firstLine.length > 60 ? `${firstLine.slice(0, 60)}...` : firstLine;
|
|
275
|
+
return `[shep doctor] ${truncated}`;
|
|
276
|
+
}
|
|
277
|
+
formatIssueBody(report) {
|
|
278
|
+
const sections = [];
|
|
279
|
+
sections.push('## Problem Description\n');
|
|
280
|
+
sections.push(report.userDescription);
|
|
281
|
+
if (report.featureId) {
|
|
282
|
+
sections.push('\n## Feature Context\n');
|
|
283
|
+
sections.push(`- **Feature ID:** ${report.featureId}`);
|
|
284
|
+
if (report.featureName)
|
|
285
|
+
sections.push(`- **Feature Name:** ${report.featureName}`);
|
|
286
|
+
if (report.featureLifecycle)
|
|
287
|
+
sections.push(`- **Lifecycle:** ${report.featureLifecycle}`);
|
|
288
|
+
if (report.featureBranch)
|
|
289
|
+
sections.push(`- **Branch:** ${report.featureBranch}`);
|
|
290
|
+
if (report.featureDescription)
|
|
291
|
+
sections.push(`- **Description:** ${report.featureDescription}`);
|
|
292
|
+
if (report.featureWorkflowConfig)
|
|
293
|
+
sections.push(`- **Workflow Config:** ${report.featureWorkflowConfig}`);
|
|
294
|
+
}
|
|
295
|
+
sections.push('\n## Environment\n');
|
|
296
|
+
sections.push(`- **shep CLI version:** ${report.cliVersion}`);
|
|
297
|
+
sections.push(`- **Node.js:** ${report.systemInfo.nodeVersion}`);
|
|
298
|
+
sections.push(`- **Platform:** ${report.systemInfo.platform} (${report.systemInfo.arch})`);
|
|
299
|
+
sections.push(`- **gh CLI:** ${report.systemInfo.ghVersion}`);
|
|
300
|
+
if (report.failedRunSummaries.length > 0) {
|
|
301
|
+
const heading = report.featureId
|
|
302
|
+
? '\n## Failed Agent Runs (feature-scoped)\n'
|
|
303
|
+
: '\n## Recent Failed Agent Runs\n';
|
|
304
|
+
sections.push(heading);
|
|
305
|
+
for (const run of report.failedRunSummaries) {
|
|
306
|
+
sections.push(`### ${run.agentName} (${run.agentType})`);
|
|
307
|
+
sections.push(`- **Error:** ${run.error}`);
|
|
308
|
+
sections.push(`- **Timestamp:** ${run.timestamp}`);
|
|
309
|
+
sections.push('');
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (report.agentRunDetails?.length) {
|
|
313
|
+
sections.push('\n## Agent Run Details\n');
|
|
314
|
+
for (const detail of report.agentRunDetails) {
|
|
315
|
+
sections.push(`<details><summary>Agent: ${detail.agentName} (${detail.agentType})</summary>\n`);
|
|
316
|
+
sections.push(`### Prompt\n\`\`\`\n${detail.prompt}\n\`\`\`\n`);
|
|
317
|
+
if (detail.result) {
|
|
318
|
+
sections.push(`### Result\n\`\`\`\n${detail.result}\n\`\`\`\n`);
|
|
319
|
+
}
|
|
320
|
+
if (detail.error) {
|
|
321
|
+
sections.push(`### Error\n\`\`\`\n${detail.error}\n\`\`\`\n`);
|
|
322
|
+
}
|
|
323
|
+
sections.push('</details>\n');
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (report.conversationMessages) {
|
|
327
|
+
const msgCount = (report.conversationMessages.match(/"id"/g) ?? []).length;
|
|
328
|
+
sections.push('\n## Conversation History\n');
|
|
329
|
+
sections.push(`<details><summary>Messages (${msgCount} messages)</summary>\n`);
|
|
330
|
+
sections.push(`\`\`\`json\n${report.conversationMessages}\n\`\`\`\n`);
|
|
331
|
+
sections.push('</details>\n');
|
|
332
|
+
}
|
|
333
|
+
if (report.featurePlan) {
|
|
334
|
+
sections.push('\n## Feature Plan\n');
|
|
335
|
+
sections.push('<details><summary>Plan & Tasks</summary>\n');
|
|
336
|
+
sections.push(`\`\`\`json\n${report.featurePlan}\n\`\`\`\n`);
|
|
337
|
+
sections.push('</details>\n');
|
|
338
|
+
}
|
|
339
|
+
// Spec files
|
|
340
|
+
const specEntries = [
|
|
341
|
+
['spec.yaml', report.specYaml],
|
|
342
|
+
['research.yaml', report.researchYaml],
|
|
343
|
+
['plan.yaml', report.planYaml],
|
|
344
|
+
['tasks.yaml', report.tasksYaml],
|
|
345
|
+
['feature.yaml', report.featureStatusYaml],
|
|
346
|
+
];
|
|
347
|
+
const hasSpecs = specEntries.some(([, v]) => v);
|
|
348
|
+
if (hasSpecs) {
|
|
349
|
+
sections.push('\n## Spec Files\n');
|
|
350
|
+
for (const [name, content] of specEntries) {
|
|
351
|
+
if (content) {
|
|
352
|
+
sections.push(`<details><summary>${name}</summary>\n`);
|
|
353
|
+
sections.push(`\`\`\`yaml\n${content}\n\`\`\`\n`);
|
|
354
|
+
sections.push('</details>\n');
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (report.workerLogs?.length) {
|
|
359
|
+
sections.push('\n## Worker Logs\n');
|
|
360
|
+
for (const log of report.workerLogs) {
|
|
361
|
+
const suffix = log.truncated ? ` (truncated, ${log.originalLength} chars total)` : '';
|
|
362
|
+
sections.push(`<details><summary>Worker log: ${log.agentName} (${log.agentRunId})${suffix}</summary>\n`);
|
|
363
|
+
sections.push(`\`\`\`\n${log.content}\n\`\`\`\n`);
|
|
364
|
+
sections.push('</details>\n');
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if (report.phaseTimings) {
|
|
368
|
+
sections.push('\n## Phase Timings\n');
|
|
369
|
+
sections.push('<details><summary>Phase timing data</summary>\n');
|
|
370
|
+
sections.push(`\`\`\`json\n${report.phaseTimings}\n\`\`\`\n`);
|
|
371
|
+
sections.push('</details>\n');
|
|
372
|
+
}
|
|
373
|
+
sections.push('\n---\n');
|
|
374
|
+
sections.push('_Reported via `shep doctor`_');
|
|
375
|
+
return sections.join('\n');
|
|
376
|
+
}
|
|
377
|
+
// -------------------------------------------------------------------------
|
|
378
|
+
// Fix Workflow (Task 11)
|
|
379
|
+
// -------------------------------------------------------------------------
|
|
380
|
+
async attemptFix(input, diagnosticReport, issueUrl, issueNumber) {
|
|
381
|
+
const isUserWorkdir = !!input.workdir;
|
|
382
|
+
const workdir = input.workdir ?? path.join(tmpdir(), `shep-doctor-${randomUUID()}`);
|
|
383
|
+
// Use a mutable result object so finally block can update cleanedUp
|
|
384
|
+
const result = {
|
|
385
|
+
diagnosticReport,
|
|
386
|
+
issueUrl,
|
|
387
|
+
issueNumber,
|
|
388
|
+
cleanedUp: false,
|
|
389
|
+
};
|
|
390
|
+
try {
|
|
391
|
+
// Ensure working directory exists
|
|
392
|
+
await mkdir(workdir, { recursive: true });
|
|
393
|
+
// Check push access (fall back to contributor flow on error)
|
|
394
|
+
let hasPushAccess = false;
|
|
395
|
+
try {
|
|
396
|
+
hasPushAccess = await this.repoService.checkPushAccess(SHEP_REPO);
|
|
397
|
+
}
|
|
398
|
+
catch {
|
|
399
|
+
// NFR-9: fall back to fork path on any detection failure
|
|
400
|
+
}
|
|
401
|
+
const flowType = hasPushAccess ? 'maintainer' : 'contributor';
|
|
402
|
+
result.flowType = flowType;
|
|
403
|
+
// Clone repository (direct or via fork)
|
|
404
|
+
let repoToClone = SHEP_REPO;
|
|
405
|
+
if (flowType === 'contributor') {
|
|
406
|
+
const { nameWithOwner } = await this.repoService.forkRepository(SHEP_REPO);
|
|
407
|
+
repoToClone = nameWithOwner;
|
|
408
|
+
}
|
|
409
|
+
await this.repoService.cloneRepository(repoToClone, workdir, undefined);
|
|
410
|
+
// Create fix branch
|
|
411
|
+
const branchName = `doctor/fix-${issueNumber}`;
|
|
412
|
+
await this.execFile('git', ['checkout', '-b', branchName], {
|
|
413
|
+
cwd: workdir,
|
|
414
|
+
});
|
|
415
|
+
// Invoke AI agent
|
|
416
|
+
try {
|
|
417
|
+
const executor = await this.agentExecutorProvider.getExecutor();
|
|
418
|
+
const prompt = this.buildFixPrompt(diagnosticReport, issueNumber);
|
|
419
|
+
await executor.execute(prompt, { cwd: workdir });
|
|
420
|
+
}
|
|
421
|
+
catch (agentError) {
|
|
422
|
+
result.error = `Fix attempt failed: ${agentError.message}`;
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
// Check if agent produced changes
|
|
426
|
+
const hasChanges = await this.prService.hasUncommittedChanges(workdir);
|
|
427
|
+
if (!hasChanges) {
|
|
428
|
+
result.error = 'Fix attempt produced no changes';
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
// Commit, push, and create PR
|
|
432
|
+
await this.prService.commitAll(workdir, `fix: address issue #${issueNumber} reported via shep doctor`);
|
|
433
|
+
await this.prService.push(workdir, branchName, true);
|
|
434
|
+
const prResult = await this.prService.createPrFromArgs(workdir, {
|
|
435
|
+
title: `fix: address shep doctor issue #${issueNumber}`,
|
|
436
|
+
body: `## Summary\n\nAutomated fix attempt for #${issueNumber}.\n\nThis PR was created by \`shep doctor\` after diagnosing a reported issue.\n\nRelates to #${issueNumber}`,
|
|
437
|
+
labels: ['shep-doctor'],
|
|
438
|
+
base: 'main',
|
|
439
|
+
repo: flowType === 'contributor' ? SHEP_REPO : undefined,
|
|
440
|
+
});
|
|
441
|
+
result.prUrl = prResult.url;
|
|
442
|
+
return result;
|
|
443
|
+
}
|
|
444
|
+
finally {
|
|
445
|
+
// Cleanup temp directory (unless user specified --workdir)
|
|
446
|
+
if (!isUserWorkdir) {
|
|
447
|
+
try {
|
|
448
|
+
await rm(workdir, { recursive: true, force: true });
|
|
449
|
+
result.cleanedUp = true;
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
// Best-effort cleanup
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
buildFixPrompt(report, issueNumber) {
|
|
458
|
+
const lines = [];
|
|
459
|
+
lines.push(`You are fixing issue #${issueNumber} in the shep-ai/cli codebase.`);
|
|
460
|
+
lines.push('');
|
|
461
|
+
lines.push('## Problem Description');
|
|
462
|
+
lines.push(report.userDescription);
|
|
463
|
+
lines.push('');
|
|
464
|
+
if (report.failedRunSummaries.length > 0) {
|
|
465
|
+
lines.push('## Error Context');
|
|
466
|
+
for (const run of report.failedRunSummaries) {
|
|
467
|
+
lines.push(`- Agent: ${run.agentName} (${run.agentType})`);
|
|
468
|
+
lines.push(` Error: ${run.error}`);
|
|
469
|
+
}
|
|
470
|
+
lines.push('');
|
|
471
|
+
}
|
|
472
|
+
lines.push('## Instructions');
|
|
473
|
+
lines.push('1. Analyze the codebase to identify the root cause');
|
|
474
|
+
lines.push('2. Implement a fix for the identified issue');
|
|
475
|
+
lines.push('3. Run tests to verify the fix works');
|
|
476
|
+
lines.push('4. Keep changes minimal and focused');
|
|
477
|
+
return lines.join('\n');
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
DoctorDiagnoseUseCase = __decorate([
|
|
481
|
+
injectable(),
|
|
482
|
+
__param(0, inject('IAgentRunRepository')),
|
|
483
|
+
__param(1, inject('IVersionService')),
|
|
484
|
+
__param(2, inject('IGitHubIssueService')),
|
|
485
|
+
__param(3, inject('IGitHubRepositoryService')),
|
|
486
|
+
__param(4, inject('IGitPrService')),
|
|
487
|
+
__param(5, inject('IAgentExecutorProvider')),
|
|
488
|
+
__param(6, inject('ExecFunction')),
|
|
489
|
+
__param(7, inject('IFeatureRepository')),
|
|
490
|
+
__param(8, inject('IPhaseTimingRepository')),
|
|
491
|
+
__metadata("design:paramtypes", [Object, Object, Object, Object, Object, Object, Function, Object, Object])
|
|
492
|
+
], DoctorDiagnoseUseCase);
|
|
493
|
+
export { DoctorDiagnoseUseCase };
|
|
@@ -417,6 +417,10 @@ export type WorkflowConfig = {
|
|
|
417
417
|
* Hide CI status badges from UI (default: true)
|
|
418
418
|
*/
|
|
419
419
|
hideCiStatus?: boolean;
|
|
420
|
+
/**
|
|
421
|
+
* Maximum number of doctor fix attempts before giving up (default: 1)
|
|
422
|
+
*/
|
|
423
|
+
doctorMaxFixAttempts?: number;
|
|
420
424
|
};
|
|
421
425
|
export declare enum AgentType {
|
|
422
426
|
ClaudeCode = "claude-code",
|
|
@@ -1652,6 +1656,187 @@ export type Evidence = {
|
|
|
1652
1656
|
*/
|
|
1653
1657
|
taskRef?: string;
|
|
1654
1658
|
};
|
|
1659
|
+
/**
|
|
1660
|
+
* Summary of a failed agent run for diagnostic reporting
|
|
1661
|
+
*/
|
|
1662
|
+
export type FailedRunSummary = {
|
|
1663
|
+
/**
|
|
1664
|
+
* Type of agent that failed (e.g. claude-code, gemini-cli)
|
|
1665
|
+
*/
|
|
1666
|
+
agentType: string;
|
|
1667
|
+
/**
|
|
1668
|
+
* Name/identifier of the agent run
|
|
1669
|
+
*/
|
|
1670
|
+
agentName: string;
|
|
1671
|
+
/**
|
|
1672
|
+
* Error message from the failed run
|
|
1673
|
+
*/
|
|
1674
|
+
error: string;
|
|
1675
|
+
/**
|
|
1676
|
+
* ISO 8601 timestamp when the failure occurred
|
|
1677
|
+
*/
|
|
1678
|
+
timestamp: string;
|
|
1679
|
+
};
|
|
1680
|
+
/**
|
|
1681
|
+
* System environment information for diagnostic reporting
|
|
1682
|
+
*/
|
|
1683
|
+
export type SystemInfo = {
|
|
1684
|
+
/**
|
|
1685
|
+
* Node.js version (e.g. v20.11.0)
|
|
1686
|
+
*/
|
|
1687
|
+
nodeVersion: string;
|
|
1688
|
+
/**
|
|
1689
|
+
* Operating system platform (e.g. darwin, linux, win32)
|
|
1690
|
+
*/
|
|
1691
|
+
platform: string;
|
|
1692
|
+
/**
|
|
1693
|
+
* CPU architecture (e.g. x64, arm64)
|
|
1694
|
+
*/
|
|
1695
|
+
arch: string;
|
|
1696
|
+
/**
|
|
1697
|
+
* gh CLI version string
|
|
1698
|
+
*/
|
|
1699
|
+
ghVersion: string;
|
|
1700
|
+
};
|
|
1701
|
+
/**
|
|
1702
|
+
* Detailed agent run information including prompt and result for diagnostic reporting
|
|
1703
|
+
*/
|
|
1704
|
+
export type AgentRunDetail = {
|
|
1705
|
+
/**
|
|
1706
|
+
* Type of agent (e.g. claude-code, gemini-cli)
|
|
1707
|
+
*/
|
|
1708
|
+
agentType: string;
|
|
1709
|
+
/**
|
|
1710
|
+
* Name/identifier of the agent run
|
|
1711
|
+
*/
|
|
1712
|
+
agentName: string;
|
|
1713
|
+
/**
|
|
1714
|
+
* Input prompt sent to the agent executor
|
|
1715
|
+
*/
|
|
1716
|
+
prompt: string;
|
|
1717
|
+
/**
|
|
1718
|
+
* Final result output from the agent (if available)
|
|
1719
|
+
*/
|
|
1720
|
+
result?: string;
|
|
1721
|
+
/**
|
|
1722
|
+
* Error message if the run failed
|
|
1723
|
+
*/
|
|
1724
|
+
error?: string;
|
|
1725
|
+
/**
|
|
1726
|
+
* ISO 8601 timestamp of the run
|
|
1727
|
+
*/
|
|
1728
|
+
timestamp: string;
|
|
1729
|
+
};
|
|
1730
|
+
/**
|
|
1731
|
+
* Worker log entry for a specific agent run
|
|
1732
|
+
*/
|
|
1733
|
+
export type WorkerLogEntry = {
|
|
1734
|
+
/**
|
|
1735
|
+
* Agent run ID this log belongs to
|
|
1736
|
+
*/
|
|
1737
|
+
agentRunId: string;
|
|
1738
|
+
/**
|
|
1739
|
+
* Name of the agent that produced this log
|
|
1740
|
+
*/
|
|
1741
|
+
agentName: string;
|
|
1742
|
+
/**
|
|
1743
|
+
* Full log file content (may be truncated)
|
|
1744
|
+
*/
|
|
1745
|
+
content: string;
|
|
1746
|
+
/**
|
|
1747
|
+
* Whether the content was truncated due to size limits
|
|
1748
|
+
*/
|
|
1749
|
+
truncated: boolean;
|
|
1750
|
+
/**
|
|
1751
|
+
* Original character count before truncation (only set when truncated)
|
|
1752
|
+
*/
|
|
1753
|
+
originalLength?: number;
|
|
1754
|
+
};
|
|
1755
|
+
/**
|
|
1756
|
+
* Structured diagnostic report collected by shep doctor for issue creation
|
|
1757
|
+
*/
|
|
1758
|
+
export type DoctorDiagnosticReport = {
|
|
1759
|
+
/**
|
|
1760
|
+
* User-provided description of the problem
|
|
1761
|
+
*/
|
|
1762
|
+
userDescription: string;
|
|
1763
|
+
/**
|
|
1764
|
+
* Summaries of recent failed agent runs
|
|
1765
|
+
*/
|
|
1766
|
+
failedRunSummaries: FailedRunSummary[];
|
|
1767
|
+
/**
|
|
1768
|
+
* System environment information
|
|
1769
|
+
*/
|
|
1770
|
+
systemInfo: SystemInfo;
|
|
1771
|
+
/**
|
|
1772
|
+
* Current shep CLI version
|
|
1773
|
+
*/
|
|
1774
|
+
cliVersion: string;
|
|
1775
|
+
/**
|
|
1776
|
+
* Feature ID when diagnosing a specific feature (optional)
|
|
1777
|
+
*/
|
|
1778
|
+
featureId?: string;
|
|
1779
|
+
/**
|
|
1780
|
+
* Feature name when diagnosing a specific feature (optional)
|
|
1781
|
+
*/
|
|
1782
|
+
featureName?: string;
|
|
1783
|
+
/**
|
|
1784
|
+
* Feature lifecycle phase (e.g. Implementation, Review)
|
|
1785
|
+
*/
|
|
1786
|
+
featureLifecycle?: string;
|
|
1787
|
+
/**
|
|
1788
|
+
* Feature git branch name
|
|
1789
|
+
*/
|
|
1790
|
+
featureBranch?: string;
|
|
1791
|
+
/**
|
|
1792
|
+
* Feature description
|
|
1793
|
+
*/
|
|
1794
|
+
featureDescription?: string;
|
|
1795
|
+
/**
|
|
1796
|
+
* JSON-serialized feature workflow configuration (fast, push, openPr, approvalGates)
|
|
1797
|
+
*/
|
|
1798
|
+
featureWorkflowConfig?: string;
|
|
1799
|
+
/**
|
|
1800
|
+
* Raw spec.yaml content
|
|
1801
|
+
*/
|
|
1802
|
+
specYaml?: string;
|
|
1803
|
+
/**
|
|
1804
|
+
* Raw research.yaml content
|
|
1805
|
+
*/
|
|
1806
|
+
researchYaml?: string;
|
|
1807
|
+
/**
|
|
1808
|
+
* Raw plan.yaml content
|
|
1809
|
+
*/
|
|
1810
|
+
planYaml?: string;
|
|
1811
|
+
/**
|
|
1812
|
+
* Raw tasks.yaml content
|
|
1813
|
+
*/
|
|
1814
|
+
tasksYaml?: string;
|
|
1815
|
+
/**
|
|
1816
|
+
* Raw feature.yaml (status tracking) content
|
|
1817
|
+
*/
|
|
1818
|
+
featureStatusYaml?: string;
|
|
1819
|
+
/**
|
|
1820
|
+
* Detailed agent run information including prompts and results
|
|
1821
|
+
*/
|
|
1822
|
+
agentRunDetails?: AgentRunDetail[];
|
|
1823
|
+
/**
|
|
1824
|
+
* JSON-serialized conversation messages (Feature.messages[])
|
|
1825
|
+
*/
|
|
1826
|
+
conversationMessages?: string;
|
|
1827
|
+
/**
|
|
1828
|
+
* JSON-serialized feature plan (Feature.plan)
|
|
1829
|
+
*/
|
|
1830
|
+
featurePlan?: string;
|
|
1831
|
+
/**
|
|
1832
|
+
* Worker execution logs for agent runs associated with this feature
|
|
1833
|
+
*/
|
|
1834
|
+
workerLogs?: WorkerLogEntry[];
|
|
1835
|
+
/**
|
|
1836
|
+
* JSON-serialized phase timing records
|
|
1837
|
+
*/
|
|
1838
|
+
phaseTimings?: string;
|
|
1839
|
+
};
|
|
1655
1840
|
export declare enum AgentStatus {
|
|
1656
1841
|
Idle = "Idle",
|
|
1657
1842
|
Running = "Running",
|