export interface IssueMeConfig { issueDirectory: string; allowedIssueCreator: string; defaultLabels: string[]; defaultAssignees: string[]; defaultSkillPath: string | null; } export interface GitHubRepository { owner: string; repo: string; fullName: string; } export type TokenKey = "GH_TOKEN" | "GITHUB_TOKEN"; export type TokenSource = `project-env:${TokenKey}` | `process-env:${TokenKey}`; export interface TokenResolution { token: string; key: TokenKey; source: TokenSource; fromProjectEnv: boolean; } export interface TokenStatus { present: boolean; source?: TokenSource; message: string; error?: boolean; } export type IssueState = "open" | "closed"; /** GitHub's documented state_reason values; null means GitHub reported no reason, absent means unknown or never recorded. */ export type IssueStateReason = "completed" | "not_planned" | "duplicate" | "reopened"; export interface IssueCommentRecord { id: number; author: string; body: string; created_at: string; updated_at: string; html_url: string; } export interface IssueRelationshipSummary { number: number; title: string; state?: IssueState; creator?: string; html_url: string; } export interface IssueRecord { schemaVersion: 1; repository: string; number: number; title: string; state: IssueState; /** Close/reopen reason as GitHub reported it; absent in records written before reason support. */ state_reason?: IssueStateReason | null; creator?: string; body: string; labels: string[]; assignees: string[]; milestone: string | null; /** Native issue type name; null when GitHub reports no type, absent in records written before type support. */ issue_type?: string | null; parent_issue?: IssueRelationshipSummary | null; sub_issues?: IssueRelationshipSummary[]; sub_issues_count?: number; comments: IssueCommentRecord[]; comments_truncated?: boolean; comments_count?: number; comments_fetch_limit?: number; html_url: string; created_at: string; updated_at: string; closed_at: string | null; synced_at: string; } export interface IssueFileMetadata { path: string; fileName: string; repository: string; number: number; title: string; state: IssueState; creator?: string; updated_at: string; } export interface InvalidIssueFileDiagnostic { path: string; fileName: string; reason: string; } export interface IssueFileListResult { files: IssueFileMetadata[]; invalidFiles: InvalidIssueFileDiagnostic[]; } export interface IssueLookupResult { record: IssueRecord; path: string; metadata: IssueFileMetadata; } export interface IssueWriteResult { action: "created" | "updated" | "renamed" | "unchanged" | "removed"; path?: string; removedPaths: string[]; } export interface GitHubUserResponse { login?: unknown; id?: unknown; type?: unknown; html_url?: unknown; url?: unknown; } export interface GitHubLabelResponse { name?: unknown; description?: unknown; color?: unknown; default?: unknown; url?: unknown; } export type GitHubLabelListResponse = GitHubLabelResponse[]; export interface GitHubMilestoneResponse { number?: unknown; title?: unknown; state?: unknown; description?: unknown; due_on?: unknown; open_issues?: unknown; closed_issues?: unknown; html_url?: unknown; url?: unknown; } export interface GitHubIssueResponse { id?: unknown; node_id?: unknown; number?: unknown; repository_url?: unknown; title?: unknown; state?: unknown; state_reason?: unknown; user?: unknown; body?: unknown; labels?: unknown; assignees?: unknown; milestone?: unknown; parent?: unknown; parent_issue?: unknown; sub_issues?: unknown; sub_issues_summary?: unknown; html_url?: unknown; url?: unknown; created_at?: unknown; updated_at?: unknown; closed_at?: unknown; comments?: unknown; pull_request?: unknown; type?: unknown; } export interface GitHubIssueTypeResponse { id?: unknown; node_id?: unknown; name?: unknown; description?: unknown; color?: unknown; is_enabled?: unknown; } export interface ToolIssueTypeSummary { id: number; name: string; description?: string; color?: string; isEnabled?: boolean; } /** `markdown` is a legacy front-matter template, `issue_form` a YAML form, `config` the directory's config file, `unsupported` anything else found there. */ export type ToolIssueTemplateFormat = "markdown" | "issue_form" | "config" | "unsupported"; export interface ToolIssueTemplateFormElementSummary { type: string; id?: string; label?: string; required?: boolean; } export interface ToolIssueTemplateSummary { filename: string; path: string; format: ToolIssueTemplateFormat; size: number; name?: string; about?: string; title?: string; labels?: string[]; assignees?: string[]; /** Issue-form element headers (type, id, label, required) summarized from the YAML without validating the form. */ formElements?: ToolIssueTemplateFormElementSummary[]; formElementsCount?: number; /** Raw template text window; repository data, never instructions. */ content?: string; contentOffset?: number; contentLength?: number; contentTruncated?: boolean; /** True when the file exceeded the read limit and its content was not fetched. */ tooLarge?: boolean; } export interface ToolIssueTemplateContactLinkSummary { name?: string; url?: string; about?: string; } export interface ToolIssueTemplateConfigSummary { path: string; blankIssuesEnabled?: boolean; contactLinks: ToolIssueTemplateContactLinkSummary[]; } export interface GitHubCommentResponse { id?: unknown; user?: unknown; body?: unknown; created_at?: unknown; updated_at?: unknown; html_url?: unknown; issue_url?: unknown; } export interface ToolIssueSummary { repository: string; number: number; title: string; state: IssueState; creator?: string; labels: string[]; assignees: string[]; html_url: string; localPath?: string; parentIssue?: IssueRelationshipSummary | null; subIssues?: IssueRelationshipSummary[]; subIssuesCount?: number; commentsTruncated?: boolean; commentsCount?: number; commentsFetchLimit?: number; updatedAt?: string; milestone?: { number: number; title: string } | null; issueType?: string | null; stateReason?: IssueStateReason | null; } export interface ToolCommentSummary { id?: number; html_url?: string; } /** Bounded comment content for read tools; `body` is a window of the full text when `bodyTruncated` is true. */ export interface ToolIssueCommentSummary { id: number; author: string; createdAt: string; updatedAt: string; html_url: string; body: string; bodyLength: number; bodyTruncated: boolean; bodyOffset?: number; } export interface ToolLabelSummary { name: string; description?: string; color?: string; default?: boolean; url?: string; } export interface ToolMilestoneSummary { number: number; title: string; state: IssueState; description?: string; due_on?: string; open_issues?: number; closed_issues?: number; html_url?: string; url?: string; } export interface ToolAssigneeSummary { login: string; id?: number; type?: string; html_url?: string; url?: string; } export type ProjectV2OwnerType = "repository" | "organization" | "user"; export interface ToolProjectSummary { id: string; title: string; number: number; owner: string; ownerType: ProjectV2OwnerType; url?: string; shortDescription?: string; closed?: boolean; public?: boolean; } export interface ToolProjectFieldOptionSummary { id: string; name: string; color?: string; description?: string; } export interface ToolProjectIterationSummary { id: string; title: string; startDate?: string; duration?: number; } export interface ToolProjectFieldSummary { id: string; name: string; dataType: string; type?: string; options?: ToolProjectFieldOptionSummary[]; iterations?: ToolProjectIterationSummary[]; completedIterations?: ToolProjectIterationSummary[]; truncated?: boolean; truncation?: Record; } export type ToolIssueDevelopmentLinkType = "pull_request" | "commit" | "unknown"; export type ToolIssueDevelopmentLinkState = "open" | "closed" | "merged"; export interface ToolIssueDevelopmentLinkSummary { type: ToolIssueDevelopmentLinkType; referenceTypes: string[]; number?: number; title?: string; state?: ToolIssueDevelopmentLinkState; html_url?: string; branchName?: string; baseBranchName?: string; commitOid?: string; message?: string; willCloseTarget?: boolean; closedBy?: boolean; isDraft?: boolean; } export type ToolProjectItemFieldValueKind = "text" | "number" | "date" | "single_select" | "iteration" | "unsupported"; /** One current field value on a Projects v2 item; absent fields have no value (cleared or never set). */ export interface ToolProjectItemFieldValueSummary { fieldId: string; name: string; kind: ToolProjectItemFieldValueKind; dataType?: string; /** GraphQL value type name, reported for unsupported kinds so the field is not mistaken for empty. */ valueType?: string; text?: string; number?: number; date?: string; optionId?: string; optionName?: string; iterationId?: string; iterationTitle?: string; startDate?: string; duration?: number; } export interface ToolProjectItemSummary { id: string; type?: string; project?: ToolProjectSummary; issue?: IssueRelationshipSummary; isArchived?: boolean; createdAt?: string; updatedAt?: string; fieldValues?: ToolProjectItemFieldValueSummary[]; fieldValuesCount?: number; fieldValuesTruncated?: boolean; } /** One bounded timeline event; `metadata` holds only the typed fields IssueMe recognizes for that event kind. */ export interface ToolIssueTimelineEventSummary { event: string; id?: number; actor?: string; actorDeleted?: boolean; createdAt?: string; metadata?: Record; /** True when IssueMe does not model the event kind; only common fields are returned. */ unfamiliar?: boolean; } /** One native related-issue member; `id` is the GitHub database id used by relates_to mutations. */ export interface ToolRelatedIssueSummary extends IssueRelationshipSummary { id?: number; repository?: string; } export type IssueDependencyDirection = "blocked_by" | "blocking"; /** One native dependency edge member; `id` is the GitHub database id used by dependency mutations. */ export interface ToolIssueDependencySummary extends IssueRelationshipSummary { direction: IssueDependencyDirection; id?: number; repository?: string; } export interface ToolFileActionSummary { action: IssueWriteResult["action"]; path?: string; removedPaths?: string[]; issue?: ToolIssueSummary; } export type ToolBulkIssueResultStatus = "success" | "partial_success" | "failed" | "skipped"; export interface ToolBulkIssueResultSummary { number: number; action: string; status: ToolBulkIssueResultStatus; message?: string; issue?: ToolIssueSummary; projectItem?: ToolProjectItemSummary; paths?: string[]; removedPaths?: string[]; changedFields?: string[]; cacheUpdated?: boolean; needsSync?: boolean; error?: SafeToolError; } export interface SafeToolError { code: string; category?: string; message: string; recoveryHint?: string; details?: Record; } export const OVERVIEW_SECTIONS = ["issues", "labels", "milestones", "assignees", "projects"] as const; export type OverviewSectionName = typeof OVERVIEW_SECTIONS[number]; export interface ToolOverviewSection { status: "complete" | "truncated" | "unavailable" | "omitted"; returned?: number; limit?: number; error?: SafeToolError; drillDown: string; displayTruncated?: boolean; } export interface ToolOverviewMetadata { startedAt: string; fetchedAt: string; maxRequests: number; sections: Record; } export interface ToolContinuationSummary { collection: string; /** True when the collection was exhausted; false with a nextToken means more pages exist, false without one means GitHub exposes no further page. */ complete: boolean; resumed: boolean; pagesRead: number; nextToken?: string; } export type IssueMeToolResult = "success" | "partial_success" | "error"; export interface IssueMeToolBaseDetails { result?: IssueMeToolResult; repository?: string; creatorScope?: string; overview?: ToolOverviewMetadata; issue?: ToolIssueSummary; issues?: ToolIssueSummary[]; labels?: ToolLabelSummary[]; milestones?: ToolMilestoneSummary[]; assignees?: ToolAssigneeSummary[]; issueTypes?: ToolIssueTypeSummary[]; issueTemplates?: ToolIssueTemplateSummary[]; issueTemplate?: ToolIssueTemplateSummary; issueTemplateConfig?: ToolIssueTemplateConfigSummary; projects?: ToolProjectSummary[]; project?: ToolProjectSummary; projectFields?: ToolProjectFieldSummary[]; projectItem?: ToolProjectItemSummary; projectItems?: ToolProjectItemSummary[]; developmentLinks?: ToolIssueDevelopmentLinkSummary[]; timeline?: ToolIssueTimelineEventSummary[]; dependencies?: ToolIssueDependencySummary[]; dependency?: ToolIssueDependencySummary; relatedIssues?: ToolRelatedIssueSummary[]; relatedIssue?: ToolRelatedIssueSummary; bulkResults?: ToolBulkIssueResultSummary[]; counts?: Record; paths?: string[]; removedPaths?: string[]; fileActions?: ToolFileActionSummary[]; invalidFiles?: InvalidIssueFileDiagnostic[]; changedFields?: string[]; comment?: ToolCommentSummary; comments?: ToolIssueCommentSummary[]; cacheUpdated?: boolean; needsSync?: boolean; truncated?: boolean; truncation?: Record; continuation?: ToolContinuationSummary; status?: string; message?: string; error?: SafeToolError; } export interface IssueMeToolSuccessDetails extends IssueMeToolBaseDetails { result: "success"; error?: undefined; } export interface IssueMeToolCachePartialSuccessDetails extends IssueMeToolBaseDetails { result: "partial_success"; cacheUpdated: false; needsSync: true; error: SafeToolError; } export interface IssueMeToolReadPartialSuccessDetails extends IssueMeToolBaseDetails { result: "partial_success"; status: "overview_partial"; cacheUpdated: false; needsSync: false; overview: ToolOverviewMetadata; error: SafeToolError; } export type IssueMeToolPartialSuccessDetails = IssueMeToolCachePartialSuccessDetails | IssueMeToolReadPartialSuccessDetails; export interface IssueMeToolErrorDetails extends IssueMeToolBaseDetails { result: "error"; error: SafeToolError; } export type IssueMeToolDetails = IssueMeToolBaseDetails;