@happyvertical/smrt-projects 0.37.4 → 0.37.5
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/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +2 -2
- package/dist/smrt-knowledge.json +4 -4
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { getProject } from "@happyvertical/projects";
|
|
|
9
9
|
import { getModuleConfig } from "@happyvertical/smrt-config";
|
|
10
10
|
import { getRepository } from "@happyvertical/repos";
|
|
11
11
|
//#region src/__smrt-register__.ts
|
|
12
|
-
ObjectRegistry.registerPackageManifest(new URL("./manifest.json", "" + import.meta.url));
|
|
12
|
+
ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":1782953437885,\"packageName\":\"@happyvertical/smrt-projects\",\"packageVersion\":\"0.37.5\",\"objects\":{\"@happyvertical/smrt-projects:IssueCollection\":{\"name\":\"issuecollection\",\"className\":\"IssueCollection\",\"qualifiedName\":\"@happyvertical/smrt-projects:IssueCollection\",\"collection\":\"issues\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/collections/Issues.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{},\"methods\":{\"discover\":{\"name\":\"discover\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findByRepository\":{\"name\":\"findByRepository\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findOpen\":{\"name\":\"findOpen\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findByLabel\":{\"name\":\"findByLabel\",\"async\":true,\"parameters\":[{\"name\":\"label\",\"type\":\"string\",\"optional\":false},{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findByAssignee\":{\"name\":\"findByAssignee\",\"async\":true,\"parameters\":[{\"name\":\"assignee\",\"type\":\"string\",\"optional\":false},{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findNeedingReview\":{\"name\":\"findNeedingReview\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findByNumber\":{\"name\":\"findByNumber\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":false},{\"name\":\"number\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"Promise<Issue | null>\",\"isStatic\":false,\"isPublic\":true},\"findWithUnincorporatedFeedback\":{\"name\":\"findWithUnincorporatedFeedback\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"batchSync\":{\"name\":\"batchSync\",\"async\":true,\"parameters\":[{\"name\":\"repository\",\"type\":\"Repository\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Issue\",\"exportName\":\"IssueCollection\",\"collectionExportName\":\"IssueCollectionCollection\",\"schema\":{\"tableName\":\"issue_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"issue_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"issue_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"issue_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"93b3c6f0\"}},\"@happyvertical/smrt-projects:ProjectCollection\":{\"name\":\"projectcollection\",\"className\":\"ProjectCollection\",\"qualifiedName\":\"@happyvertical/smrt-projects:ProjectCollection\",\"collection\":\"projects\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/collections/Projects.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{},\"methods\":{\"findByTitle\":{\"name\":\"findByTitle\",\"async\":true,\"parameters\":[{\"name\":\"title\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Project | null>\",\"isStatic\":false,\"isPublic\":true},\"findByOwner\":{\"name\":\"findByOwner\",\"async\":true,\"parameters\":[{\"name\":\"owner\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Project[]>\",\"isStatic\":false,\"isPublic\":true},\"findByProvider\":{\"name\":\"findByProvider\",\"async\":true,\"parameters\":[{\"name\":\"providerType\",\"type\":\"ProjectProviderType\",\"optional\":false}],\"returnType\":\"Promise<Project[]>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreate\":{\"name\":\"getOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"projectId\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Project>\",\"isStatic\":false,\"isPublic\":true},\"syncAll\":{\"name\":\"syncAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Project[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithItemsInStatus\":{\"name\":\"findWithItemsInStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Project[]>\",\"isStatic\":false,\"isPublic\":true},\"getStatistics\":{\"name\":\"getStatistics\",\"async\":true,\"parameters\":[{\"name\":\"projectId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Project[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Project[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Project[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Project\",\"exportName\":\"ProjectCollection\",\"collectionExportName\":\"ProjectCollectionCollection\",\"schema\":{\"tableName\":\"project_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"project_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"project_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"project_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"f713c200\"}},\"@happyvertical/smrt-projects:PullRequestCollection\":{\"name\":\"pullrequestcollection\",\"className\":\"PullRequestCollection\",\"qualifiedName\":\"@happyvertical/smrt-projects:PullRequestCollection\",\"collection\":\"issues\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/collections/PullRequests.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{},\"methods\":{\"discover\":{\"name\":\"discover\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findByRepository\":{\"name\":\"findByRepository\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findOpen\":{\"name\":\"findOpen\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findDrafts\":{\"name\":\"findDrafts\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findReadyToMerge\":{\"name\":\"findReadyToMerge\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findByBranch\":{\"name\":\"findByBranch\",\"async\":true,\"parameters\":[{\"name\":\"branch\",\"type\":\"string\",\"optional\":false},{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findByNumber\":{\"name\":\"findByNumber\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":false},{\"name\":\"number\",\"type\":\"number\",\"optional\":false}],\"returnType\":\"Promise<PullRequest | null>\",\"isStatic\":false,\"isPublic\":true},\"findAIReadyToMerge\":{\"name\":\"findAIReadyToMerge\",\"async\":true,\"parameters\":[{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findBySize\":{\"name\":\"findBySize\",\"async\":true,\"parameters\":[{\"name\":\"size\",\"type\":\"'xs' | 's' | 'm' | 'l' | 'xl'\",\"optional\":false},{\"name\":\"repositoryId\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"batchSync\":{\"name\":\"batchSync\",\"async\":true,\"parameters\":[{\"name\":\"repository\",\"type\":\"Repository\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableName\":\"issues\"},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"PullRequest\",\"exportName\":\"PullRequestCollection\",\"collectionExportName\":\"PullRequestCollectionCollection\",\"schema\":{\"tableName\":\"issues\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"issues\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"issues_id_idx\",\"columns\":[\"id\"]},{\"name\":\"issues_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"798511d0\"}},\"@happyvertical/smrt-projects:RepositoryCollection\":{\"name\":\"repositorycollection\",\"className\":\"RepositoryCollection\",\"qualifiedName\":\"@happyvertical/smrt-projects:RepositoryCollection\",\"collection\":\"repositories\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/collections/Repositories.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{},\"methods\":{\"findByFullName\":{\"name\":\"findByFullName\",\"async\":true,\"parameters\":[{\"name\":\"owner\",\"type\":\"string\",\"optional\":false},{\"name\":\"name\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Repository | null>\",\"isStatic\":false,\"isPublic\":true},\"findByOwner\":{\"name\":\"findByOwner\",\"async\":true,\"parameters\":[{\"name\":\"owner\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Repository[]>\",\"isStatic\":false,\"isPublic\":true},\"findByProvider\":{\"name\":\"findByProvider\",\"async\":true,\"parameters\":[{\"name\":\"providerType\",\"type\":\"RepositoryProviderType\",\"optional\":false}],\"returnType\":\"Promise<Repository[]>\",\"isStatic\":false,\"isPublic\":true},\"getOrCreate\":{\"name\":\"getOrCreate\",\"async\":true,\"parameters\":[{\"name\":\"owner\",\"type\":\"string\",\"optional\":false},{\"name\":\"name\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Repository>\",\"isStatic\":false,\"isPublic\":true},\"syncAll\":{\"name\":\"syncAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Repository[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithOpenIssues\":{\"name\":\"findWithOpenIssues\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Repository[]>\",\"isStatic\":false,\"isPublic\":true},\"findByTenant\":{\"name\":\"findByTenant\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Repository[]>\",\"isStatic\":false,\"isPublic\":true},\"findGlobal\":{\"name\":\"findGlobal\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Repository[]>\",\"isStatic\":false,\"isPublic\":true},\"findWithGlobals\":{\"name\":\"findWithGlobals\",\"async\":true,\"parameters\":[{\"name\":\"tenantId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Repository[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"Repository\",\"exportName\":\"RepositoryCollection\",\"collectionExportName\":\"RepositoryCollectionCollection\",\"schema\":{\"tableName\":\"repository_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"repository_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"repository_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"repository_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"a9b3565e\"}},\"@happyvertical/smrt-projects:Comment\":{\"name\":\"comment\",\"className\":\"Comment\",\"qualifiedName\":\"@happyvertical/smrt-projects:Comment\",\"collection\":\"comments\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/models/Comment.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"issueId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Issue\"},\"commentId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"body\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"author\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"createdAt\":{\"type\":\"datetime\",\"required\":false},\"updatedAt\":{\"type\":\"datetime\",\"required\":false},\"url\":{\"type\":\"text\",\"required\":false,\"default\":\"\"}},\"methods\":{\"isQuestion\":{\"name\":\"isQuestion\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"isApproval\":{\"name\":\"isApproval\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"requestsChanges\":{\"name\":\"requestsChanges\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"extractActionItems\":{\"name\":\"extractActionItems\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"summarize\":{\"name\":\"summarize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"getSentiment\":{\"name\":\"getSentiment\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<'positive' | 'negative' | 'neutral'>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"include\":[\"list\",\"get\"]},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"Comment\",\"collectionExportName\":\"CommentCollection\",\"schema\":{\"tableName\":\"comments\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"comments\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"issue_id\\\" UUID,\\n \\\"comment_id\\\" TEXT DEFAULT '',\\n \\\"body\\\" TEXT DEFAULT '',\\n \\\"author\\\" TEXT DEFAULT '',\\n \\\"url\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"issue_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false},\"comment_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"body\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"author\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"url\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"comments_id_idx\",\"columns\":[\"id\"]},{\"name\":\"comments_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"ed899e3f\"}},\"@happyvertical/smrt-projects:Issue\":{\"name\":\"issue\",\"className\":\"Issue\",\"qualifiedName\":\"@happyvertical/smrt-projects:Issue\",\"collection\":\"issues\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/models/Issue.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"repositoryId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Repository\",\"_meta\":{\"required\":true}},\"number\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"nodeId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"title\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"body\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"open\"},\"author\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"labels\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"assignees\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"commentsCount\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"lastSyncedAt\":{\"type\":\"datetime\",\"required\":false},\"originalBody\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"synthesisCount\":{\"type\":\"integer\",\"required\":false,\"default\":0}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getRepository\":{\"name\":\"getRepository\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Repository>\",\"isStatic\":false,\"isPublic\":true},\"getClient\":{\"name\":\"getClient\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<IRepository>\",\"isStatic\":false,\"isPublic\":true},\"clearCache\":{\"name\":\"clearCache\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"sync\":{\"name\":\"sync\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SyncOptions\",\"optional\":true}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"getComments\":{\"name\":\"getComments\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Comment[]>\",\"isStatic\":false,\"isPublic\":true},\"addComment\":{\"name\":\"addComment\",\"async\":true,\"parameters\":[{\"name\":\"body\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Comment>\",\"isStatic\":false,\"isPublic\":true},\"incorporateFeedback\":{\"name\":\"incorporateFeedback\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IncorporateFeedbackOptions\",\"optional\":true}],\"returnType\":\"Promise<IncorporateFeedbackResult>\",\"isStatic\":false,\"isPublic\":true},\"rollback\":{\"name\":\"rollback\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"needsReview\":{\"name\":\"needsReview\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"isBugReport\":{\"name\":\"isBugReport\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"isFeatureRequest\":{\"name\":\"isFeatureRequest\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"suggestLabels\":{\"name\":\"suggestLabels\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"close\":{\"name\":\"close\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addLabels\":{\"name\":\"addLabels\",\"async\":true,\"parameters\":[{\"name\":\"labels\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeLabel\":{\"name\":\"removeLabel\",\"async\":true,\"parameters\":[{\"name\":\"label\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"assign\":{\"name\":\"assign\",\"async\":true,\"parameters\":[{\"name\":\"assignees\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getUrl\":{\"name\":\"getUrl\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"sync\",\"incorporateFeedback\"]},\"cli\":{\"include\":[\"list\",\"get\",\"sync\",\"incorporateFeedback\",\"rollback\"],\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"Issue\",\"collectionExportName\":\"IssueCollection\",\"validationRules\":[{\"field\":\"repositoryId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"issues\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"issues\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"repository_id\\\" UUID,\\n \\\"number\\\" INTEGER DEFAULT 0,\\n \\\"node_id\\\" TEXT DEFAULT '',\\n \\\"title\\\" TEXT DEFAULT '',\\n \\\"body\\\" TEXT DEFAULT '',\\n \\\"state\\\" TEXT DEFAULT 'open',\\n \\\"author\\\" TEXT DEFAULT '',\\n \\\"labels\\\" JSON DEFAULT '[]',\\n \\\"assignees\\\" JSON DEFAULT '[]',\\n \\\"comments_count\\\" INTEGER DEFAULT 0,\\n \\\"last_synced_at\\\" TIMESTAMP,\\n \\\"original_body\\\" TEXT DEFAULT '',\\n \\\"synthesis_count\\\" INTEGER DEFAULT 0,\\n \\\"head_ref\\\" TEXT DEFAULT '',\\n \\\"base_ref\\\" TEXT DEFAULT '',\\n \\\"merged\\\" BOOLEAN DEFAULT FALSE,\\n \\\"merged_at\\\" TIMESTAMP,\\n \\\"mergeable\\\" BOOLEAN DEFAULT TRUE,\\n \\\"draft\\\" BOOLEAN DEFAULT FALSE,\\n \\\"additions\\\" INTEGER DEFAULT 0,\\n \\\"deletions\\\" INTEGER DEFAULT 0,\\n \\\"changed_files\\\" INTEGER DEFAULT 0\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"repository_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false},\"number\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"node_id\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"body\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"open\"},\"author\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"labels\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"assignees\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"comments_count\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"last_synced_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"original_body\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"synthesis_count\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"head_ref\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"base_ref\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"merged\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":false},\"merged_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"mergeable\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true},\"draft\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":false},\"additions\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"deletions\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"changed_files\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0}},\"indexes\":[{\"name\":\"issues_id_idx\",\"columns\":[\"id\"]},{\"name\":\"issues_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"issues_meta_type_idx\",\"columns\":[\"_meta_type\"]}],\"version\":\"e187bb4a\"}},\"@happyvertical/smrt-projects:Label\":{\"name\":\"label\",\"className\":\"Label\",\"qualifiedName\":\"@happyvertical/smrt-projects:Label\",\"collection\":\"labels\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/models/Label.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{\"repositoryId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"Repository\"},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"color\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"}},\"methods\":{\"isTypeLabel\":{\"name\":\"isTypeLabel\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isPriorityLabel\":{\"name\":\"isPriorityLabel\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"isStatusLabel\":{\"name\":\"isStatusLabel\",\"async\":false,\"parameters\":[],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"getCategory\":{\"name\":\"getCategory\",\"async\":false,\"parameters\":[],\"returnType\":\"'type' | 'priority' | 'status' | 'area' | 'other'\",\"isStatic\":false,\"isPublic\":true},\"getPriorityLevel\":{\"name\":\"getPriorityLevel\",\"async\":false,\"parameters\":[],\"returnType\":\"number | null\",\"isStatic\":false,\"isPublic\":true},\"getHexColor\":{\"name\":\"getHexColor\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":false,\"isPublic\":true},\"createInRepository\":{\"name\":\"createInRepository\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"updateInRepository\":{\"name\":\"updateInRepository\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"create\"]},\"cli\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]}},\"extends\":\"SmrtObject\",\"exportName\":\"Label\",\"collectionExportName\":\"LabelCollection\",\"schema\":{\"tableName\":\"labels\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"labels\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"repository_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"color\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT ''\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"repository_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false,\"unique\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"color\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"}},\"indexes\":[{\"name\":\"labels_id_idx\",\"columns\":[\"id\"]},{\"name\":\"labels_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"698e39f8\"}},\"@happyvertical/smrt-projects:Project\":{\"name\":\"project\",\"className\":\"Project\",\"qualifiedName\":\"@happyvertical/smrt-projects:Project\",\"collection\":\"projects\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/models/Project.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"projectId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"projectNumber\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"title\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"owner\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"url\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"providerType\":{\"type\":\"text\",\"required\":false,\"default\":\"github\"},\"tokenConfigKey\":{\"type\":\"text\",\"required\":false,\"default\":\"GITHUB_TOKEN\"},\"statuses\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"fields\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"statusFieldId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"statusOptions\":{\"type\":\"json\",\"required\":false,\"default\":{}},\"lastSyncedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getClient\":{\"name\":\"getClient\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<IProject>\",\"isStatic\":false,\"isPublic\":true},\"clearClient\":{\"name\":\"clearClient\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"sync\":{\"name\":\"sync\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SyncOptions\",\"optional\":true}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"addItem\":{\"name\":\"addItem\",\"async\":true,\"parameters\":[{\"name\":\"item\",\"type\":\"Issue | PullRequest\",\"optional\":false}],\"returnType\":\"Promise<ProjectItem>\",\"isStatic\":false,\"isPublic\":true},\"removeItem\":{\"name\":\"removeItem\",\"async\":true,\"parameters\":[{\"name\":\"itemId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getItem\":{\"name\":\"getItem\",\"async\":true,\"parameters\":[{\"name\":\"itemId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProjectItem | null>\",\"isStatic\":false,\"isPublic\":true},\"listItems\":{\"name\":\"listItems\",\"async\":true,\"parameters\":[{\"name\":\"filters\",\"type\":\"ItemFilters\",\"optional\":true}],\"returnType\":\"Promise<ProjectItem[]>\",\"isStatic\":false,\"isPublic\":true},\"updateItemStatus\":{\"name\":\"updateItemStatus\",\"async\":true,\"parameters\":[{\"name\":\"itemId\",\"type\":\"string\",\"optional\":false},{\"name\":\"status\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"updateItemField\":{\"name\":\"updateItemField\",\"async\":true,\"parameters\":[{\"name\":\"itemId\",\"type\":\"string\",\"optional\":false},{\"name\":\"fieldId\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getStatuses\":{\"name\":\"getStatuses\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ProjectStatus[]>\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<ProjectField[]>\",\"isStatic\":false,\"isPublic\":true},\"getItemsByStatus\":{\"name\":\"getItemsByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<ProjectItem[]>\",\"isStatic\":false,\"isPublic\":true},\"moveItem\":{\"name\":\"moveItem\",\"async\":true,\"parameters\":[{\"name\":\"item\",\"type\":\"Issue | PullRequest\",\"optional\":false},{\"name\":\"status\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"analyzeHealth\":{\"name\":\"analyzeHealth\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"getByTitle\":{\"name\":\"getByTitle\",\"async\":true,\"parameters\":[{\"name\":\"title\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<Project | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"sync\",\"addItem\",\"updateItemStatus\"]},\"cli\":{\"include\":[\"list\",\"get\",\"sync\",\"addItem\",\"updateItemStatus\",\"listItems\"],\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"Project\",\"collectionExportName\":\"ProjectCollection\",\"schema\":{\"tableName\":\"projects\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"projects\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"project_id\\\" TEXT DEFAULT '',\\n \\\"project_number\\\" INTEGER DEFAULT 0,\\n \\\"title\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"owner\\\" TEXT DEFAULT '',\\n \\\"url\\\" TEXT DEFAULT '',\\n \\\"provider_type\\\" TEXT DEFAULT 'github',\\n \\\"token_config_key\\\" TEXT DEFAULT 'GITHUB_TOKEN',\\n \\\"statuses\\\" JSON DEFAULT '[]',\\n \\\"fields\\\" JSON DEFAULT '[]',\\n \\\"status_field_id\\\" TEXT DEFAULT '',\\n \\\"status_options\\\" JSON DEFAULT '{}',\\n \\\"last_synced_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"project_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"project_number\":{\"type\":\"INTEGER\",\"notNull\":false,\"unique\":false,\"default\":0},\"title\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"owner\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"url\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"provider_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"github\"},\"token_config_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"GITHUB_TOKEN\"},\"statuses\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":[]},\"fields\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":[]},\"status_field_id\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"status_options\":{\"type\":\"JSON\",\"notNull\":false,\"unique\":false,\"default\":{}},\"last_synced_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"projects_id_idx\",\"columns\":[\"id\"]},{\"name\":\"projects_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"2e8c344a\"}},\"@happyvertical/smrt-projects:PullRequest\":{\"name\":\"pullrequest\",\"className\":\"PullRequest\",\"qualifiedName\":\"@happyvertical/smrt-projects:PullRequest\",\"collection\":\"issues\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/models/PullRequest.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"repositoryId\":{\"type\":\"foreignKey\",\"required\":true,\"related\":\"Repository\",\"_meta\":{\"required\":true}},\"number\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"nodeId\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"title\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"body\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"open\"},\"author\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"labels\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"assignees\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"commentsCount\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"lastSyncedAt\":{\"type\":\"datetime\",\"required\":false},\"originalBody\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"synthesisCount\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"headRef\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"baseRef\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"merged\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"mergedAt\":{\"type\":\"datetime\",\"required\":false},\"mergeable\":{\"type\":\"boolean\",\"required\":false,\"default\":true},\"draft\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"additions\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"deletions\":{\"type\":\"integer\",\"required\":false,\"default\":0},\"changedFiles\":{\"type\":\"integer\",\"required\":false,\"default\":0}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getRepository\":{\"name\":\"getRepository\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Repository>\",\"isStatic\":false,\"isPublic\":true},\"getClient\":{\"name\":\"getClient\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<IRepository>\",\"isStatic\":false,\"isPublic\":true},\"clearCache\":{\"name\":\"clearCache\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"sync\":{\"name\":\"sync\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SyncOptions\",\"optional\":true}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"getComments\":{\"name\":\"getComments\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Comment[]>\",\"isStatic\":false,\"isPublic\":true},\"addComment\":{\"name\":\"addComment\",\"async\":true,\"parameters\":[{\"name\":\"body\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<Comment>\",\"isStatic\":false,\"isPublic\":true},\"incorporateFeedback\":{\"name\":\"incorporateFeedback\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"IncorporateFeedbackOptions\",\"optional\":true}],\"returnType\":\"Promise<IncorporateFeedbackResult>\",\"isStatic\":false,\"isPublic\":true},\"rollback\":{\"name\":\"rollback\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<object>\",\"isStatic\":false,\"isPublic\":true},\"needsReview\":{\"name\":\"needsReview\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"isBugReport\":{\"name\":\"isBugReport\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"isFeatureRequest\":{\"name\":\"isFeatureRequest\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"suggestLabels\":{\"name\":\"suggestLabels\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"close\":{\"name\":\"close\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"addLabels\":{\"name\":\"addLabels\",\"async\":true,\"parameters\":[{\"name\":\"labels\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"removeLabel\":{\"name\":\"removeLabel\",\"async\":true,\"parameters\":[{\"name\":\"label\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"assign\":{\"name\":\"assign\",\"async\":true,\"parameters\":[{\"name\":\"assignees\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getUrl\":{\"name\":\"getUrl\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":false,\"isPublic\":true},\"summarize\":{\"name\":\"summarize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"merge\":{\"name\":\"merge\",\"async\":true,\"parameters\":[{\"name\":\"method\",\"type\":\"MergeMethod\",\"optional\":true,\"default\":\"squash\"}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"markReady\":{\"name\":\"markReady\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"convertToDraft\":{\"name\":\"convertToDraft\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"requestReviewers\":{\"name\":\"requestReviewers\",\"async\":true,\"parameters\":[{\"name\":\"reviewers\",\"type\":\"string[]\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"findLinkedIssue\":{\"name\":\"findLinkedIssue\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Issue | null>\",\"isStatic\":false,\"isPublic\":true},\"isReadyToMerge\":{\"name\":\"isReadyToMerge\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"suggestReviewers\":{\"name\":\"suggestReviewers\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string[]>\",\"isStatic\":false,\"isPublic\":true},\"getChangeSize\":{\"name\":\"getChangeSize\",\"async\":false,\"parameters\":[],\"returnType\":\"'xs' | 's' | 'm' | 'l' | 'xl'\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"sync\",\"summarize\",\"merge\"]},\"cli\":{\"include\":[\"list\",\"get\",\"sync\",\"summarize\",\"merge\",\"markReady\"],\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"tableName\":\"issues\",\"tableStrategy\":\"sti\"},\"extends\":\"Issue\",\"exportName\":\"PullRequest\",\"collectionExportName\":\"PullRequestCollection\",\"validationRules\":[{\"field\":\"repositoryId\",\"rule\":\"required\",\"fieldType\":\"foreignKey\"}],\"schema\":{\"tableName\":\"issues\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"issues\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"repository_id\\\" UUID,\\n \\\"number\\\" INTEGER DEFAULT 0,\\n \\\"node_id\\\" TEXT DEFAULT '',\\n \\\"title\\\" TEXT DEFAULT '',\\n \\\"body\\\" TEXT DEFAULT '',\\n \\\"state\\\" TEXT DEFAULT 'open',\\n \\\"author\\\" TEXT DEFAULT '',\\n \\\"labels\\\" JSON DEFAULT '[]',\\n \\\"assignees\\\" JSON DEFAULT '[]',\\n \\\"comments_count\\\" INTEGER DEFAULT 0,\\n \\\"last_synced_at\\\" TIMESTAMP,\\n \\\"original_body\\\" TEXT DEFAULT '',\\n \\\"synthesis_count\\\" INTEGER DEFAULT 0,\\n \\\"head_ref\\\" TEXT DEFAULT '',\\n \\\"base_ref\\\" TEXT DEFAULT '',\\n \\\"merged\\\" BOOLEAN DEFAULT FALSE,\\n \\\"merged_at\\\" TIMESTAMP,\\n \\\"mergeable\\\" BOOLEAN DEFAULT TRUE,\\n \\\"draft\\\" BOOLEAN DEFAULT FALSE,\\n \\\"additions\\\" INTEGER DEFAULT 0,\\n \\\"deletions\\\" INTEGER DEFAULT 0,\\n \\\"changed_files\\\" INTEGER DEFAULT 0\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"repository_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false},\"number\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"node_id\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"title\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"body\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"open\"},\"author\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"labels\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"assignees\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"comments_count\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"last_synced_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"original_body\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"synthesis_count\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"head_ref\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"base_ref\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"merged\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":false},\"merged_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"mergeable\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true},\"draft\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":false},\"additions\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"deletions\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0},\"changed_files\":{\"type\":\"INTEGER\",\"notNull\":false,\"default\":0}},\"indexes\":[{\"name\":\"issues_id_idx\",\"columns\":[\"id\"]},{\"name\":\"issues_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"issues_meta_type_idx\",\"columns\":[\"_meta_type\"]}],\"version\":\"f42d9cf0\"}},\"@happyvertical/smrt-projects:Repository\":{\"name\":\"repository\",\"className\":\"Repository\",\"qualifiedName\":\"@happyvertical/smrt-projects:Repository\",\"collection\":\"repositories\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/projects/src/models/Repository.ts\",\"packageName\":\"@happyvertical/smrt-projects\",\"fields\":{\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"owner\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"fullName\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"defaultBranch\":{\"type\":\"text\",\"required\":false,\"default\":\"main\"},\"isPrivate\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"providerType\":{\"type\":\"text\",\"required\":false,\"default\":\"github\"},\"baseUrl\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"tokenConfigKey\":{\"type\":\"text\",\"required\":false,\"default\":\"GITHUB_TOKEN\"},\"lastSyncedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getClient\":{\"name\":\"getClient\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<IRepository>\",\"isStatic\":false,\"isPublic\":true},\"clearClient\":{\"name\":\"clearClient\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"sync\":{\"name\":\"sync\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"SyncOptions\",\"optional\":true}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"getIssues\":{\"name\":\"getIssues\",\"async\":true,\"parameters\":[{\"name\":\"filters\",\"type\":\"SearchFilters\",\"optional\":true}],\"returnType\":\"Promise<Issue[]>\",\"isStatic\":false,\"isPublic\":true},\"getPullRequests\":{\"name\":\"getPullRequests\",\"async\":true,\"parameters\":[{\"name\":\"filters\",\"type\":\"SearchFilters\",\"optional\":true}],\"returnType\":\"Promise<PullRequest[]>\",\"isStatic\":false,\"isPublic\":true},\"createIssue\":{\"name\":\"createIssue\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"CreateIssueInput\",\"optional\":false}],\"returnType\":\"Promise<Issue>\",\"isStatic\":false,\"isPublic\":true},\"createPullRequest\":{\"name\":\"createPullRequest\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"CreatePRInput\",\"optional\":false}],\"returnType\":\"Promise<PullRequest>\",\"isStatic\":false,\"isPublic\":true},\"hasOpenIssuesMatching\":{\"name\":\"hasOpenIssuesMatching\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"summarizeActivity\":{\"name\":\"summarizeActivity\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string>\",\"isStatic\":false,\"isPublic\":true},\"getByFullName\":{\"name\":\"getByFullName\",\"async\":true,\"parameters\":[{\"name\":\"owner\",\"type\":\"string\",\"optional\":false},{\"name\":\"name\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"SmrtObjectOptions\",\"optional\":true}],\"returnType\":\"Promise<Repository | null>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\"]},\"mcp\":{\"include\":[\"list\",\"get\",\"sync\"]},\"cli\":{\"include\":[\"list\",\"get\",\"sync\",\"create\"],\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"Repository\",\"collectionExportName\":\"RepositoryCollection\",\"schema\":{\"tableName\":\"repositories\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"repositories\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"owner\\\" TEXT DEFAULT '',\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"full_name\\\" TEXT DEFAULT '',\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"default_branch\\\" TEXT DEFAULT 'main',\\n \\\"is_private\\\" BOOLEAN DEFAULT FALSE,\\n \\\"provider_type\\\" TEXT DEFAULT 'github',\\n \\\"base_url\\\" TEXT DEFAULT '',\\n \\\"token_config_key\\\" TEXT DEFAULT 'GITHUB_TOKEN',\\n \\\"last_synced_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false,\"unique\":false},\"owner\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"full_name\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"default_branch\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"main\"},\"is_private\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"unique\":false,\"default\":false},\"provider_type\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"github\"},\"base_url\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"\"},\"token_config_key\":{\"type\":\"TEXT\",\"notNull\":false,\"unique\":false,\"default\":\"GITHUB_TOKEN\"},\"last_synced_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false,\"unique\":false}},\"indexes\":[{\"name\":\"repositories_id_idx\",\"columns\":[\"id\"]},{\"name\":\"repositories_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"c302a5e5\"}}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-core\",\"@happyvertical/smrt-prompts\",\"@happyvertical/smrt-tenancy\"]}"));
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region src/collections/Issues.ts
|
|
15
15
|
var Issues_exports = /* @__PURE__ */ __exportAll({ IssueCollection: () => IssueCollection });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/__smrt-register__.ts","../src/collections/Issues.ts","../src/models/Project.ts","../src/collections/Projects.ts","../src/collections/PullRequests.ts","../src/models/Repository.ts","../src/collections/Repositories.ts","../src/models/Comment.ts","../src/models/Label.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * IssueCollection - Collection manager for Issue objects\n *\n * Provides querying and discovery operations for Issue entities.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Issue } from '../models/Issue';\nimport type { Repository } from '../models/Repository';\nimport type { SearchFilters } from '../types';\n\nexport class IssueCollection extends SmrtCollection<Issue> {\n static readonly _itemClass = Issue;\n\n /**\n * Discover issues from a repository and sync to database\n *\n * This method:\n * 1. Fetches issues from the provider via SDK\n * 2. Creates/updates SMRT Issue records in the database\n * 3. Returns the synced Issue objects\n *\n * @param options - Discovery options\n * @returns Array of Issue objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<Issue[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error('Repository must be saved before discovering issues');\n }\n\n const repoClient = await repository.getClient();\n\n // Fetch issues from provider\n const remoteIssues = await repoClient.searchIssues('', filters);\n\n const issues: Issue[] = [];\n\n for (const remote of remoteIssues) {\n // Find existing issue by repository + number\n let issue = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!issue) {\n // Create new issue\n issue = await this.create({\n repositoryId,\n number: remote.number,\n nodeId: remote.id,\n title: remote.title,\n body: remote.body,\n state: remote.state,\n author: remote.author.login,\n labels: remote.labels.map((l) => l.name),\n assignees: remote.assignees.map((a) => a.login),\n commentsCount: remote.commentsCount,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing issue\n issue.nodeId = remote.id;\n issue.title = remote.title;\n issue.body = remote.body;\n issue.state = remote.state;\n issue.author = remote.author.login;\n issue.labels = remote.labels.map((l) => l.name);\n issue.assignees = remote.assignees.map((a) => a.login);\n issue.commentsCount = remote.commentsCount;\n issue.lastSyncedAt = new Date();\n }\n\n await issue.save();\n issues.push(issue);\n }\n\n return issues;\n }\n\n /**\n * Find issues by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of issues\n */\n async findByRepository(repositoryId: string): Promise<Issue[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open issues\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open issues\n */\n async findOpen(repositoryId?: string): Promise<Issue[]> {\n const where: Record<string, unknown> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find issues by label\n *\n * @param label - Label name\n * @param repositoryId - Optional repository filter\n * @returns Array of issues with the label\n */\n async findByLabel(label: string, repositoryId?: string): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by label (JSON array search)\n return issues.filter((issue) => issue.labels.includes(label));\n }\n\n /**\n * Find issues by assignee\n *\n * @param assignee - Assignee login\n * @param repositoryId - Optional repository filter\n * @returns Array of issues assigned to the user\n */\n async findByAssignee(\n assignee: string,\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by assignee (JSON array search)\n return issues.filter((issue) => issue.assignees.includes(assignee));\n }\n\n /**\n * Find issues needing review (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues that need review\n */\n async findNeedingReview(repositoryId?: string): Promise<Issue[]> {\n const openIssues = await this.findOpen(repositoryId);\n const needingReview: Issue[] = [];\n\n for (const issue of openIssues) {\n if (await issue.needsReview()) {\n needingReview.push(issue);\n }\n }\n\n return needingReview;\n }\n\n /**\n * Find issue by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - Issue number\n * @returns Issue or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<Issue | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Get issues with unincorporated feedback\n *\n * Issues that have comments but haven't had feedback incorporated\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues\n */\n async findWithUnincorporatedFeedback(\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.findOpen(repositoryId);\n\n return issues.filter(\n (issue) => issue.commentsCount > 0 && issue.synthesisCount === 0,\n );\n }\n\n /**\n * Batch sync issues from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced issues\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<Issue[]> {\n const issues = await this.findByRepository(repository.id as string);\n const synced: Issue[] = [];\n\n for (const issue of issues) {\n await issue.sync(options);\n synced.push(issue);\n }\n\n return synced;\n }\n\n /**\n * Find issues by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of issues for the tenant\n */\n async findByTenant(tenantId: string): Promise<Issue[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global issues (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global issues\n */\n async findGlobal(): Promise<Issue[]> {\n return queryGlobal<Issue>(this);\n }\n\n /**\n * Find issues for a tenant plus all global issues.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global issues\n */\n async findWithGlobals(tenantId: string): Promise<Issue[]> {\n return queryWithGlobals<Issue>(this, tenantId, 'Issue.findWithGlobals');\n }\n}\n","/**\n * Project model - SMRT wrapper for project board operations\n *\n * Provides persistent project tracking with provider-agnostic operations.\n * Uses @happyvertical/projects SDK for actual API calls.\n */\n\nimport { getProject } from '@happyvertical/projects';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n IProject,\n ItemFilters,\n ProjectField,\n ProjectItem,\n ProjectProviderType,\n ProjectStatus,\n SDKProject,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface ProjectOptions extends SmrtObjectOptions {\n projectId?: string;\n projectNumber?: number;\n title?: string;\n description?: string;\n owner?: string;\n url?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statuses?: ProjectStatus[];\n fields?: ProjectField[];\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'addItem', 'updateItemStatus'] },\n // sync/addItem/updateItemStatus/listItems are operator commands invoked\n // in-process via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: [\n 'list',\n 'get',\n 'sync',\n 'addItem',\n 'updateItemStatus',\n 'listItems',\n ],\n skipApiCheck: true,\n },\n})\nexport class Project extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Provider-specific project ID (e.g., GitHub GraphQL node ID)\n */\n projectId: string = '';\n\n /**\n * Human-readable project number\n */\n projectNumber: number = 0;\n\n /**\n * Project title\n */\n title: string = '';\n\n /**\n * Project description\n */\n description: string = '';\n\n /**\n * Project owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Project URL\n */\n url: string = '';\n\n /**\n * Project provider type\n */\n providerType: ProjectProviderType = 'github';\n\n /**\n * Environment variable name or config key for token resolution\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Available statuses (columns) in the project\n */\n statuses: ProjectStatus[] = [];\n\n /**\n * Custom fields defined in the project\n */\n fields: ProjectField[] = [];\n\n /**\n * Status field ID for GitHub Projects V2\n */\n statusFieldId: string = '';\n\n /**\n * Maps status name to option ID (for GitHub Projects V2)\n */\n statusOptions: Record<string, string> = {};\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached project client (not persisted)\n */\n private _client?: IProject;\n\n constructor(options: ProjectOptions = {}) {\n super(options);\n if (options.projectId !== undefined) this.projectId = options.projectId;\n if (options.projectNumber !== undefined)\n this.projectNumber = options.projectNumber;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.url !== undefined) this.url = options.url;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.statuses !== undefined) this.statuses = options.statuses;\n if (options.fields !== undefined) this.fields = options.fields;\n if (options.statusFieldId !== undefined)\n this.statusFieldId = options.statusFieldId;\n if (options.statusOptions !== undefined)\n this.statusOptions = options.statusOptions;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Get the project client, resolving token from config\n *\n * @returns Project client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IProject> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getProject({\n type: this.providerType,\n projectId: this.projectId,\n token,\n statusFieldId: this.statusFieldId || undefined,\n statusOptions:\n Object.keys(this.statusOptions).length > 0\n ? this.statusOptions\n : undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync project metadata from the provider\n *\n * @param options - Sync options\n * @returns This project with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const projectData: SDKProject = await client.getProject();\n\n // Update fields from remote\n this.title = projectData.title;\n this.description = projectData.description || '';\n this.owner = projectData.owner;\n this.url = projectData.url;\n this.statuses = projectData.statuses;\n this.fields = projectData.fields;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Add an issue or PR to this project\n *\n * @param item - Issue or PullRequest to add\n * @returns Created ProjectItem\n */\n async addItem(item: Issue | PullRequest): Promise<ProjectItem> {\n if (!item.nodeId) {\n throw new Error('Item must have a nodeId (sync the item first)');\n }\n\n const client = await this.getClient();\n return await client.addItem(item.nodeId);\n }\n\n /**\n * Remove an item from this project\n *\n * @param itemId - Project item ID to remove\n */\n async removeItem(itemId: string): Promise<void> {\n const client = await this.getClient();\n await client.removeItem(itemId);\n }\n\n /**\n * Get a specific item from the project\n *\n * @param itemId - Project item ID\n * @returns ProjectItem or null\n */\n async getItem(itemId: string): Promise<ProjectItem | null> {\n const client = await this.getClient();\n return await client.getItem(itemId);\n }\n\n /**\n * List items in this project\n *\n * @param filters - Optional filters\n * @returns Array of ProjectItems\n */\n async listItems(filters?: ItemFilters): Promise<ProjectItem[]> {\n const client = await this.getClient();\n return await client.listItems(filters);\n }\n\n /**\n * Update an item's status (column)\n *\n * @param itemId - Project item ID\n * @param status - New status name\n */\n async updateItemStatus(itemId: string, status: string): Promise<void> {\n const client = await this.getClient();\n await client.updateItemStatus(itemId, status);\n }\n\n /**\n * Update an item's custom field\n *\n * @param itemId - Project item ID\n * @param fieldId - Field ID\n * @param value - New value\n */\n async updateItemField(\n itemId: string,\n fieldId: string,\n value: unknown,\n ): Promise<void> {\n const client = await this.getClient();\n await client.updateItemField(itemId, fieldId, value);\n }\n\n /**\n * Get available statuses\n *\n * @returns Array of status definitions\n */\n async getStatuses(): Promise<ProjectStatus[]> {\n if (this.statuses.length > 0) {\n return this.statuses;\n }\n\n const client = await this.getClient();\n this.statuses = await client.listStatuses();\n await this.save();\n return this.statuses;\n }\n\n /**\n * Get available fields\n *\n * @returns Array of field definitions\n */\n async getFields(): Promise<ProjectField[]> {\n if (this.fields.length > 0) {\n return this.fields;\n }\n\n const client = await this.getClient();\n this.fields = await client.listFields();\n await this.save();\n return this.fields;\n }\n\n /**\n * Get items in a specific status/column\n *\n * @param status - Status name\n * @returns Array of ProjectItems in that status\n */\n async getItemsByStatus(status: string): Promise<ProjectItem[]> {\n return await this.listItems({ status });\n }\n\n /**\n * Move an item to a new status\n *\n * @param item - Issue or PullRequest\n * @param status - Target status name\n */\n async moveItem(item: Issue | PullRequest, status: string): Promise<void> {\n // First, find the item in the project\n const items = await this.listItems();\n const projectItem = items.find((i) => i.contentId === item.nodeId);\n\n if (!projectItem) {\n throw new Error('Item not found in project');\n }\n\n await this.updateItemStatus(projectItem.id, status);\n }\n\n /**\n * AI-powered: Analyze project health and suggest improvements\n *\n * @returns Analysis of project status\n */\n async analyzeHealth(): Promise<string> {\n const items = await this.listItems();\n const statuses = await this.getStatuses();\n\n // Count items by status\n const statusCounts: Record<string, number> = {};\n for (const status of statuses) {\n statusCounts[status.name] = items.filter(\n (i) => i.status === status.name,\n ).length;\n }\n\n return await this.do(\n `Analyze the health of this project board and suggest improvements.\n\n Project: ${this.title}\n Description: ${this.description}\n\n Item distribution by status:\n ${Object.entries(statusCounts)\n .map(([status, count]) => `- ${status}: ${count} items`)\n .join('\\n')}\n\n Total items: ${items.length}\n\n Provide:\n 1. Overall health assessment\n 2. Potential bottlenecks\n 3. Suggestions for improvement`,\n // Title/description/status counts hand-rolled above; skip do()'s\n // object-data injection so the board context is not duplicated.\n { includeData: false },\n );\n }\n\n /**\n * Get project by title\n *\n * @param title - Project title\n * @param options - Additional options\n * @returns Project or null\n */\n static async getByTitle(\n title: string,\n options: SmrtObjectOptions = {},\n ): Promise<Project | null> {\n const { ProjectCollection } = await import('../collections/Projects');\n const collection = await ProjectCollection.create(options);\n return await collection.findByTitle(title);\n }\n}\n","/**\n * ProjectCollection - Collection manager for Project objects\n *\n * Provides querying and discovery operations for Project entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Project } from '../models/Project';\nimport type { ProjectProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class ProjectCollection extends SmrtCollection<Project> {\n static readonly _itemClass = Project;\n\n /**\n * Find project by title\n *\n * @param title - Project title\n * @returns Project or null\n */\n async findByTitle(title: string): Promise<Project | null> {\n const results = await this.list({\n where: { title },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find projects by owner\n *\n * @param owner - Project owner (organization or user)\n * @returns Array of projects\n */\n async findByOwner(owner: string): Promise<Project[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find projects by provider type\n *\n * @param providerType - Provider type\n * @returns Array of projects\n */\n async findByProvider(providerType: ProjectProviderType): Promise<Project[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a project by ID\n *\n * @param projectId - Provider-specific project ID\n * @param options - Additional options for creation\n * @returns Project (existing or newly created)\n */\n async getOrCreate(\n projectId: string,\n options: {\n title?: string;\n owner?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n } = {},\n ): Promise<Project> {\n let project = await this.findOne({\n where: { projectId },\n });\n\n if (!project) {\n project = await this.create({\n projectId,\n title: options.title || '',\n owner: options.owner || '',\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n statusFieldId: options.statusFieldId || '',\n statusOptions: options.statusOptions || {},\n });\n await project.save();\n\n // Sync to get full project data\n await project.sync({ force: true });\n }\n\n return project;\n }\n\n /**\n * Sync all projects\n *\n * @param options - Sync options\n * @returns Array of synced projects\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Project[]> {\n const projects = await this.list({});\n const synced: Project[] = [];\n\n for (const project of projects) {\n await project.sync(options);\n synced.push(project);\n }\n\n return synced;\n }\n\n /**\n * Find projects with items in a specific status\n *\n * @param status - Status name\n * @returns Array of projects\n */\n async findWithItemsInStatus(status: string): Promise<Project[]> {\n const projects = await this.list({});\n const matching: Project[] = [];\n\n for (const project of projects) {\n try {\n const items = await project.getItemsByStatus(status);\n if (items.length > 0) {\n matching.push(project);\n }\n } catch (error) {\n // Log error and skip projects we can't access\n logger.warn(`Error accessing items for project ${project.projectId}`, {\n error: error instanceof Error ? error.message : error,\n });\n }\n }\n\n return matching;\n }\n\n /**\n * Get project statistics\n *\n * @param projectId - Project ID\n * @returns Statistics object\n */\n async getStatistics(projectId: string): Promise<{\n totalItems: number;\n itemsByStatus: Record<string, number>;\n itemsByType: Record<string, number>;\n }> {\n const project = await this.findOne({ where: { projectId } });\n if (!project) {\n throw new Error(`Project ${projectId} not found`);\n }\n\n const items = await project.listItems();\n const statuses = await project.getStatuses();\n\n const itemsByStatus: Record<string, number> = {};\n for (const status of statuses) {\n itemsByStatus[status.name] = 0;\n }\n\n const itemsByType: Record<string, number> = {\n Issue: 0,\n PullRequest: 0,\n DraftIssue: 0,\n };\n\n for (const item of items) {\n if (item.status && itemsByStatus[item.status] !== undefined) {\n itemsByStatus[item.status]++;\n }\n if (itemsByType[item.type] !== undefined) {\n itemsByType[item.type]++;\n }\n }\n\n return {\n totalItems: items.length,\n itemsByStatus,\n itemsByType,\n };\n }\n\n /**\n * Find projects by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of projects for the tenant\n */\n async findByTenant(tenantId: string): Promise<Project[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global projects (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global projects\n */\n async findGlobal(): Promise<Project[]> {\n return queryGlobal<Project>(this);\n }\n\n /**\n * Find projects for a tenant plus all global projects.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global projects\n */\n async findWithGlobals(tenantId: string): Promise<Project[]> {\n return queryWithGlobals<Project>(this, tenantId, 'Project.findWithGlobals');\n }\n}\n","/**\n * PullRequestCollection - Collection manager for PullRequest objects\n *\n * Provides querying and discovery operations for PullRequest entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { PullRequest } from '../models/PullRequest';\nimport type { Repository } from '../models/Repository';\nimport type { SDKPullRequest, SearchFilters } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class PullRequestCollection extends SmrtCollection<PullRequest> {\n static readonly _itemClass = PullRequest;\n\n /**\n * Discover pull requests from a repository and sync to database\n *\n * @param options - Discovery options\n * @returns Array of PullRequest objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<PullRequest[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error(\n 'Repository must be saved before discovering pull requests',\n );\n }\n\n const repoClient = await repository.getClient();\n\n // Note: searchIssues with type filter would get PRs in GitHub\n // For now, we'll search for all and filter\n const remoteItems = await repoClient.searchIssues('is:pr', filters);\n\n const pullRequests: PullRequest[] = [];\n\n for (const remote of remoteItems) {\n // Get full PR data\n let prData: SDKPullRequest;\n try {\n prData = await repoClient.getPullRequest(remote.number);\n } catch (error) {\n // Log error and skip PR - could be rate limiting, auth, or access issues\n logger.warn(\n `Failed to fetch PR #${remote.number} from ${repository.owner}/${repository.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n continue;\n }\n\n // Find existing PR by repository + number\n let pr = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!pr) {\n // Create new PR\n pr = await this.create({\n repositoryId,\n number: prData.number,\n nodeId: prData.id,\n title: prData.title,\n body: prData.body,\n state: prData.state,\n author: prData.author.login,\n labels: prData.labels.map((l) => l.name),\n assignees: prData.assignees.map((a) => a.login),\n commentsCount: prData.commentsCount,\n headRef: prData.headRef,\n baseRef: prData.baseRef,\n merged: prData.merged,\n mergedAt: prData.mergedAt || null,\n mergeable: prData.mergeable,\n draft: prData.draft,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing PR\n pr.nodeId = prData.id;\n pr.title = prData.title;\n pr.body = prData.body;\n pr.state = prData.state;\n pr.author = prData.author.login;\n pr.labels = prData.labels.map((l) => l.name);\n pr.assignees = prData.assignees.map((a) => a.login);\n pr.commentsCount = prData.commentsCount;\n pr.headRef = prData.headRef;\n pr.baseRef = prData.baseRef;\n pr.merged = prData.merged;\n pr.mergedAt = prData.mergedAt || null;\n pr.mergeable = prData.mergeable;\n pr.draft = prData.draft;\n pr.lastSyncedAt = new Date();\n }\n\n await pr.save();\n pullRequests.push(pr);\n }\n\n return pullRequests;\n }\n\n /**\n * Find PRs by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of PRs\n */\n async findByRepository(repositoryId: string): Promise<PullRequest[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open PRs\n */\n async findOpen(repositoryId?: string): Promise<PullRequest[]> {\n const where: Record<string, unknown> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find draft PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of draft PRs\n */\n async findDrafts(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => pr.draft);\n }\n\n /**\n * Find PRs ready to merge\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of mergeable PRs\n */\n async findReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => !pr.draft && pr.mergeable);\n }\n\n /**\n * Find PRs by branch\n *\n * @param branch - Branch name (head or base)\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findByBranch(\n branch: string,\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n return prs.filter((pr) => pr.headRef === branch || pr.baseRef === branch);\n }\n\n /**\n * Find PR by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - PR number\n * @returns PullRequest or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<PullRequest | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find PRs ready to merge (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs that are ready\n */\n async findAIReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n const ready: PullRequest[] = [];\n\n for (const pr of openPRs) {\n if (await pr.isReadyToMerge()) {\n ready.push(pr);\n }\n }\n\n return ready;\n }\n\n /**\n * Get PRs by change size\n *\n * @param size - Size classification\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findBySize(\n size: 'xs' | 's' | 'm' | 'l' | 'xl',\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.findOpen(repositoryId);\n return prs.filter((pr) => pr.getChangeSize() === size);\n }\n\n /**\n * Batch sync PRs from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced PRs\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<PullRequest[]> {\n const prs = await this.findByRepository(repository.id as string);\n const synced: PullRequest[] = [];\n\n for (const pr of prs) {\n await pr.sync(options);\n synced.push(pr);\n }\n\n return synced;\n }\n\n /**\n * Find pull requests by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of pull requests for the tenant\n */\n async findByTenant(tenantId: string): Promise<PullRequest[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global pull requests (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global pull requests\n */\n async findGlobal(): Promise<PullRequest[]> {\n return queryGlobal<PullRequest>(this);\n }\n\n /**\n * Find pull requests for a tenant plus all global pull requests.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global pull requests\n */\n async findWithGlobals(tenantId: string): Promise<PullRequest[]> {\n return queryWithGlobals<PullRequest>(\n this,\n tenantId,\n 'PullRequest.findWithGlobals',\n );\n }\n}\n","/**\n * Repository model - SMRT wrapper for repository operations\n *\n * Provides persistent repository tracking with provider-agnostic operations.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { getRepository } from '@happyvertical/repos';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n CreateIssueInput,\n CreatePRInput,\n IRepository,\n RepositoryProviderType,\n SDKRepository,\n SearchFilters,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface RepositoryOptions extends SmrtObjectOptions {\n owner?: string;\n name?: string;\n fullName?: string;\n description?: string;\n defaultBranch?: string;\n isPrivate?: boolean;\n providerType?: RepositoryProviderType;\n baseUrl?: string;\n tokenConfigKey?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync'] },\n // sync is an operator command invoked in-process via the CLI;\n // it intentionally isn't exposed over HTTP today.\n cli: { include: ['list', 'get', 'sync', 'create'], skipApiCheck: true },\n})\nexport class Repository extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Repository owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Repository name\n */\n name: string = '';\n\n /**\n * Full name in owner/repo format\n */\n fullName: string = '';\n\n /**\n * Repository description\n */\n description: string = '';\n\n /**\n * Default branch name\n */\n defaultBranch: string = 'main';\n\n /**\n * Whether repository is private\n */\n isPrivate: boolean = false;\n\n /**\n * Repository provider type\n */\n providerType: RepositoryProviderType = 'github';\n\n /**\n * Base URL for self-hosted instances (GitHub Enterprise, GitLab self-hosted, etc.)\n */\n baseUrl: string = '';\n\n /**\n * Environment variable name or config key for token resolution\n * The token is NOT stored - only the key name is persisted\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached repository client (not persisted)\n */\n private _client?: IRepository;\n\n constructor(options: RepositoryOptions = {}) {\n super(options);\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.name !== undefined) this.name = options.name;\n if (options.fullName !== undefined) this.fullName = options.fullName;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.defaultBranch !== undefined)\n this.defaultBranch = options.defaultBranch;\n if (options.isPrivate !== undefined) this.isPrivate = options.isPrivate;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.baseUrl !== undefined) this.baseUrl = options.baseUrl;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Get the repository client, resolving token from config\n *\n * Token resolution order:\n * 1. Environment variable matching tokenConfigKey\n * 2. Module config value matching tokenConfigKey\n *\n * @returns Repository client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IRepository> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getRepository({\n type: this.providerType,\n owner: this.owner,\n repo: this.name,\n token,\n baseUrl: this.baseUrl || undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client (useful after token refresh)\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync repository metadata from the provider\n *\n * @param options - Sync options\n * @returns This repository with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const repoData: SDKRepository = await client.getRepository();\n\n // Update fields from remote\n this.owner = repoData.owner;\n this.name = repoData.name;\n this.fullName = `${repoData.owner}/${repoData.name}`;\n this.description = repoData.description;\n this.defaultBranch = repoData.defaultBranch;\n this.isPrivate = repoData.isPrivate;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Get issues from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of Issue objects (SMRT models)\n */\n async getIssues(filters?: SearchFilters): Promise<Issue[]> {\n const { IssueCollection } = await import('../collections/Issues');\n const collection = await IssueCollection.create(this.options);\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Get pull requests from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of PullRequest objects (SMRT models)\n */\n async getPullRequests(filters?: SearchFilters): Promise<PullRequest[]> {\n const { PullRequestCollection } = await import(\n '../collections/PullRequests'\n );\n const collection = await PullRequestCollection.create(this.options);\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Create a new issue in this repository\n *\n * @param data - Issue creation data\n * @returns Created Issue (SMRT model)\n */\n async createIssue(data: CreateIssueInput): Promise<Issue> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating issues');\n }\n\n const client = await this.getClient();\n const created = await client.createIssue(data);\n\n // Create SMRT Issue from remote data\n const { Issue } = await import('./Issue');\n const issue = new Issue({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n lastSyncedAt: new Date(),\n });\n\n // Directly-constructed models must be initialized before save() can access\n // the database connection (SmrtCollection.create() does this internally).\n await issue.initialize();\n await issue.save();\n return issue;\n }\n\n /**\n * Create a new pull request in this repository\n *\n * @param data - PR creation data\n * @returns Created PullRequest (SMRT model)\n */\n async createPullRequest(data: CreatePRInput): Promise<PullRequest> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating pull requests');\n }\n\n const client = await this.getClient();\n const created = await client.createPullRequest(data);\n\n // Create SMRT PullRequest from remote data\n const { PullRequest } = await import('./PullRequest');\n const pr = new PullRequest({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n headRef: created.headRef,\n baseRef: created.baseRef,\n merged: created.merged,\n draft: created.draft,\n lastSyncedAt: new Date(),\n });\n\n // Directly-constructed models must be initialized before save() can access\n // the database connection (SmrtCollection.create() does this internally).\n await pr.initialize();\n await pr.save();\n return pr;\n }\n\n /**\n * Check if this repository has any open issues matching criteria\n *\n * @param criteria - Natural language description of what to check\n * @returns True if matching issues exist\n */\n async hasOpenIssuesMatching(criteria: string): Promise<boolean> {\n const issues = await this.getIssues({ state: 'open' });\n if (issues.length === 0) return false;\n\n return await this.is(\n `This repository has open issues matching: ${criteria}. ` +\n `Current open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}`,\n );\n }\n\n /**\n * Generate a summary of repository activity\n *\n * @returns AI-generated summary\n */\n async summarizeActivity(): Promise<string> {\n const issues = await this.getIssues({ state: 'open', limit: 10 });\n const prs = await this.getPullRequests({ state: 'open', limit: 10 });\n\n return await this.do(\n `Summarize the current activity in this repository. ` +\n `Open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}. ` +\n `Open PRs: ${prs.map((p) => `#${p.number}: ${p.title}`).join(', ')}.`,\n );\n }\n\n /**\n * Get repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options\n * @returns Repository or null if not found\n */\n static async getByFullName(\n owner: string,\n name: string,\n options: SmrtObjectOptions = {},\n ): Promise<Repository | null> {\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await RepositoryCollection.create(options);\n return await collection.findByFullName(owner, name);\n }\n}\n","/**\n * RepositoryCollection - Collection manager for Repository objects\n *\n * Provides querying and discovery operations for Repository entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Repository } from '../models/Repository';\nimport type { RepositoryProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class RepositoryCollection extends SmrtCollection<Repository> {\n static readonly _itemClass = Repository;\n\n /**\n * Find a repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @returns Repository or null\n */\n async findByFullName(\n owner: string,\n name: string,\n ): Promise<Repository | null> {\n const results = await this.list({\n where: { owner, name },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find repositories by owner\n *\n * @param owner - Repository owner\n * @returns Array of repositories\n */\n async findByOwner(owner: string): Promise<Repository[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find repositories by provider type\n *\n * @param providerType - Provider type\n * @returns Array of repositories\n */\n async findByProvider(\n providerType: RepositoryProviderType,\n ): Promise<Repository[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a repository by owner/name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options for creation\n * @returns Repository (existing or newly created)\n */\n async getOrCreate(\n owner: string,\n name: string,\n options: {\n providerType?: RepositoryProviderType;\n tokenConfigKey?: string;\n baseUrl?: string;\n } = {},\n ): Promise<Repository> {\n let repo = await this.findByFullName(owner, name);\n\n if (!repo) {\n repo = await this.create({\n owner,\n name,\n fullName: `${owner}/${name}`,\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n baseUrl: options.baseUrl || '',\n });\n await repo.save();\n }\n\n return repo;\n }\n\n /**\n * Sync all repositories\n *\n * @param options - Sync options\n * @returns Array of synced repositories\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Repository[]> {\n const repos = await this.list({});\n const synced: Repository[] = [];\n\n for (const repo of repos) {\n await repo.sync(options);\n synced.push(repo);\n }\n\n return synced;\n }\n\n /**\n * Find repositories with open issues\n *\n * @returns Array of repositories with at least one open issue\n */\n async findWithOpenIssues(): Promise<Repository[]> {\n const repos = await this.list({});\n const withIssues: Repository[] = [];\n\n for (const repo of repos) {\n try {\n const issues = await repo.getIssues({ state: 'open', limit: 1 });\n if (issues.length > 0) {\n withIssues.push(repo);\n }\n } catch (error) {\n // Log error and skip repos we can't access\n logger.warn(\n `Error accessing issues for repository ${repo.owner}/${repo.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n }\n }\n\n return withIssues;\n }\n\n /**\n * Find repositories by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of repositories for the tenant\n */\n async findByTenant(tenantId: string): Promise<Repository[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global repositories (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global repositories\n */\n async findGlobal(): Promise<Repository[]> {\n return queryGlobal<Repository>(this);\n }\n\n /**\n * Find repositories for a tenant plus all global repositories.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global repositories\n */\n async findWithGlobals(tenantId: string): Promise<Repository[]> {\n return queryWithGlobals<Repository>(\n this,\n tenantId,\n 'Repository.findWithGlobals',\n );\n }\n}\n","/**\n * Comment model - SMRT wrapper for issue/PR comments\n *\n * Represents a comment on an issue or pull request.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nconst logger = createLogger({ level: 'info' });\n\nexport interface CommentOptions extends SmrtObjectOptions {\n issueId?: string;\n commentId?: string;\n body?: string;\n author?: string;\n createdAt?: Date;\n updatedAt?: Date;\n url?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class Comment extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Issue this comment belongs to\n */\n @foreignKey('Issue')\n issueId?: string;\n\n /**\n * Provider-specific comment ID\n */\n commentId: string = '';\n\n /**\n * Comment body text\n */\n body: string = '';\n\n /**\n * Comment author's login\n */\n author: string = '';\n\n /**\n * When the comment was created\n */\n createdAt: Date | null = null;\n\n /**\n * When the comment was last updated\n */\n updatedAt: Date | null = null;\n\n /**\n * Comment URL\n */\n url: string = '';\n\n constructor(options: CommentOptions = {}) {\n super(options);\n if (options.issueId !== undefined) this.issueId = options.issueId;\n if (options.commentId !== undefined) this.commentId = options.commentId;\n if (options.body !== undefined) this.body = options.body;\n if (options.author !== undefined) this.author = options.author;\n if (options.createdAt !== undefined) this.createdAt = options.createdAt;\n if (options.updatedAt !== undefined) this.updatedAt = options.updatedAt;\n if (options.url !== undefined) this.url = options.url;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * AI-powered: Check if this comment contains a question\n */\n async isQuestion(): Promise<boolean> {\n return await this.is(\n 'This comment contains a question or request for clarification',\n );\n }\n\n /**\n * AI-powered: Check if this comment contains approval\n */\n async isApproval(): Promise<boolean> {\n return await this.is(\n 'This comment expresses approval, agreement, or a positive response (LGTM, +1, approved, etc.)',\n );\n }\n\n /**\n * AI-powered: Check if this comment requests changes\n */\n async requestsChanges(): Promise<boolean> {\n return await this.is(\n 'This comment requests changes, modifications, or improvements to the issue/PR',\n );\n }\n\n /**\n * AI-powered: Extract action items from this comment\n *\n * @returns Array of action items\n */\n async extractActionItems(): Promise<string[]> {\n const result = await this.do(\n `Extract any action items, tasks, or requests from this comment.\n Return a JSON array of strings, each representing one action item.\n If no action items, return an empty array [].\n Only return the JSON array, nothing else.\n\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n try {\n return JSON.parse(result);\n } catch (error) {\n logger.warn('Failed to parse action items JSON', {\n error: error instanceof Error ? error.message : error,\n response: result,\n });\n return [];\n }\n }\n\n /**\n * AI-powered: Summarize this comment\n *\n * @returns Brief summary\n */\n async summarize(): Promise<string> {\n return await this.do(\n `Summarize this comment in one sentence.\n Comment by ${this.author}: ${this.body}`,\n // Author + body hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n }\n\n /**\n * Get the sentiment of this comment\n *\n * @returns Sentiment classification\n */\n async getSentiment(): Promise<'positive' | 'negative' | 'neutral'> {\n const result = await this.do(\n `Classify the sentiment of this comment as exactly one of: positive, negative, neutral\n Only return one word.\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n const normalized = result.toLowerCase().trim();\n if (normalized.includes('positive')) return 'positive';\n if (normalized.includes('negative')) return 'negative';\n return 'neutral';\n }\n}\n","/**\n * Label model - SMRT wrapper for repository labels\n *\n * Represents a label that can be applied to issues and PRs.\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\nexport interface LabelOptions extends SmrtObjectOptions {\n repositoryId?: string;\n name?: string;\n color?: string;\n description?: string;\n}\n\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: { include: ['list', 'get', 'create', 'update', 'delete'] },\n})\nexport class Label extends SmrtObject {\n /**\n * Repository this label belongs to\n */\n @foreignKey('Repository')\n repositoryId?: string;\n\n /**\n * Label name\n */\n name: string = '';\n\n /**\n * Label color (hex without #)\n */\n color: string = '';\n\n /**\n * Label description\n */\n description: string = '';\n\n constructor(options: LabelOptions = {}) {\n super(options);\n if (options.repositoryId !== undefined)\n this.repositoryId = options.repositoryId;\n if (options.name !== undefined) this.name = options.name;\n if (options.color !== undefined) this.color = options.color;\n if (options.description !== undefined)\n this.description = options.description;\n }\n\n /**\n * Check if this is a type label (bug, feature, etc.)\n */\n isTypeLabel(): boolean {\n const typePatterns = [\n /^type:/i,\n /^kind:/i,\n /^bug$/i,\n /^feature$/i,\n /^enhancement$/i,\n /^docs$/i,\n /^chore$/i,\n ];\n return typePatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a priority label\n */\n isPriorityLabel(): boolean {\n const priorityPatterns = [\n /^p[0-4]$/i,\n /^priority:/i,\n /^critical$/i,\n /^high$/i,\n /^medium$/i,\n /^low$/i,\n ];\n return priorityPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a status label\n */\n isStatusLabel(): boolean {\n const statusPatterns = [\n /^status:/i,\n /^wip$/i,\n /^in.?progress$/i,\n /^blocked$/i,\n /^needs.?review$/i,\n /^ready$/i,\n ];\n return statusPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Get the label category\n *\n * @returns Category name\n */\n getCategory(): 'type' | 'priority' | 'status' | 'area' | 'other' {\n if (this.isTypeLabel()) return 'type';\n if (this.isPriorityLabel()) return 'priority';\n if (this.isStatusLabel()) return 'status';\n if (this.name.includes(':')) return 'area';\n return 'other';\n }\n\n /**\n * Parse priority level from label name\n *\n * @returns Priority level 0-4 or null\n */\n getPriorityLevel(): number | null {\n const match = this.name.match(/p([0-4])/i);\n if (match) {\n return parseInt(match[1], 10);\n }\n if (/critical/i.test(this.name)) return 0;\n if (/high/i.test(this.name)) return 1;\n if (/medium/i.test(this.name)) return 2;\n if (/low/i.test(this.name)) return 3;\n return null;\n }\n\n /**\n * Get label with # prefix for hex color\n */\n getHexColor(): string {\n return this.color.startsWith('#') ? this.color : `#${this.color}`;\n }\n\n /**\n * Create a label in the repository\n */\n async createInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await RepositoryCollection.create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.createLabel({\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n\n /**\n * Update this label in the repository\n */\n async updateInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await RepositoryCollection.create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.updateLabel(this.name, {\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/__smrt-register__.ts","../src/collections/Issues.ts","../src/models/Project.ts","../src/collections/Projects.ts","../src/collections/PullRequests.ts","../src/models/Repository.ts","../src/collections/Repositories.ts","../src/models/Comment.ts","../src/models/Label.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// During library builds, smrtPlugin replaces this entire module with generated\n// code that embeds the scanned manifest inline (#1506/#1507) — published dists\n// never resolve this URL, so downstream bundlers cannot break registration by\n// relocating the compiled module away from dist/manifest.json. The runtime\n// lookup below is the fallback for source-mode runs without that transform.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * IssueCollection - Collection manager for Issue objects\n *\n * Provides querying and discovery operations for Issue entities.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Issue } from '../models/Issue';\nimport type { Repository } from '../models/Repository';\nimport type { SearchFilters } from '../types';\n\nexport class IssueCollection extends SmrtCollection<Issue> {\n static readonly _itemClass = Issue;\n\n /**\n * Discover issues from a repository and sync to database\n *\n * This method:\n * 1. Fetches issues from the provider via SDK\n * 2. Creates/updates SMRT Issue records in the database\n * 3. Returns the synced Issue objects\n *\n * @param options - Discovery options\n * @returns Array of Issue objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<Issue[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error('Repository must be saved before discovering issues');\n }\n\n const repoClient = await repository.getClient();\n\n // Fetch issues from provider\n const remoteIssues = await repoClient.searchIssues('', filters);\n\n const issues: Issue[] = [];\n\n for (const remote of remoteIssues) {\n // Find existing issue by repository + number\n let issue = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!issue) {\n // Create new issue\n issue = await this.create({\n repositoryId,\n number: remote.number,\n nodeId: remote.id,\n title: remote.title,\n body: remote.body,\n state: remote.state,\n author: remote.author.login,\n labels: remote.labels.map((l) => l.name),\n assignees: remote.assignees.map((a) => a.login),\n commentsCount: remote.commentsCount,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing issue\n issue.nodeId = remote.id;\n issue.title = remote.title;\n issue.body = remote.body;\n issue.state = remote.state;\n issue.author = remote.author.login;\n issue.labels = remote.labels.map((l) => l.name);\n issue.assignees = remote.assignees.map((a) => a.login);\n issue.commentsCount = remote.commentsCount;\n issue.lastSyncedAt = new Date();\n }\n\n await issue.save();\n issues.push(issue);\n }\n\n return issues;\n }\n\n /**\n * Find issues by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of issues\n */\n async findByRepository(repositoryId: string): Promise<Issue[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open issues\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open issues\n */\n async findOpen(repositoryId?: string): Promise<Issue[]> {\n const where: Record<string, unknown> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find issues by label\n *\n * @param label - Label name\n * @param repositoryId - Optional repository filter\n * @returns Array of issues with the label\n */\n async findByLabel(label: string, repositoryId?: string): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by label (JSON array search)\n return issues.filter((issue) => issue.labels.includes(label));\n }\n\n /**\n * Find issues by assignee\n *\n * @param assignee - Assignee login\n * @param repositoryId - Optional repository filter\n * @returns Array of issues assigned to the user\n */\n async findByAssignee(\n assignee: string,\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n // Filter by assignee (JSON array search)\n return issues.filter((issue) => issue.assignees.includes(assignee));\n }\n\n /**\n * Find issues needing review (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues that need review\n */\n async findNeedingReview(repositoryId?: string): Promise<Issue[]> {\n const openIssues = await this.findOpen(repositoryId);\n const needingReview: Issue[] = [];\n\n for (const issue of openIssues) {\n if (await issue.needsReview()) {\n needingReview.push(issue);\n }\n }\n\n return needingReview;\n }\n\n /**\n * Find issue by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - Issue number\n * @returns Issue or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<Issue | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Get issues with unincorporated feedback\n *\n * Issues that have comments but haven't had feedback incorporated\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of issues\n */\n async findWithUnincorporatedFeedback(\n repositoryId?: string,\n ): Promise<Issue[]> {\n const issues = await this.findOpen(repositoryId);\n\n return issues.filter(\n (issue) => issue.commentsCount > 0 && issue.synthesisCount === 0,\n );\n }\n\n /**\n * Batch sync issues from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced issues\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<Issue[]> {\n const issues = await this.findByRepository(repository.id as string);\n const synced: Issue[] = [];\n\n for (const issue of issues) {\n await issue.sync(options);\n synced.push(issue);\n }\n\n return synced;\n }\n\n /**\n * Find issues by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of issues for the tenant\n */\n async findByTenant(tenantId: string): Promise<Issue[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global issues (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global issues\n */\n async findGlobal(): Promise<Issue[]> {\n return queryGlobal<Issue>(this);\n }\n\n /**\n * Find issues for a tenant plus all global issues.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global issues\n */\n async findWithGlobals(tenantId: string): Promise<Issue[]> {\n return queryWithGlobals<Issue>(this, tenantId, 'Issue.findWithGlobals');\n }\n}\n","/**\n * Project model - SMRT wrapper for project board operations\n *\n * Provides persistent project tracking with provider-agnostic operations.\n * Uses @happyvertical/projects SDK for actual API calls.\n */\n\nimport { getProject } from '@happyvertical/projects';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n IProject,\n ItemFilters,\n ProjectField,\n ProjectItem,\n ProjectProviderType,\n ProjectStatus,\n SDKProject,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface ProjectOptions extends SmrtObjectOptions {\n projectId?: string;\n projectNumber?: number;\n title?: string;\n description?: string;\n owner?: string;\n url?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statuses?: ProjectStatus[];\n fields?: ProjectField[];\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync', 'addItem', 'updateItemStatus'] },\n // sync/addItem/updateItemStatus/listItems are operator commands invoked\n // in-process via the CLI; they intentionally aren't exposed over HTTP today.\n cli: {\n include: [\n 'list',\n 'get',\n 'sync',\n 'addItem',\n 'updateItemStatus',\n 'listItems',\n ],\n skipApiCheck: true,\n },\n})\nexport class Project extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Provider-specific project ID (e.g., GitHub GraphQL node ID)\n */\n projectId: string = '';\n\n /**\n * Human-readable project number\n */\n projectNumber: number = 0;\n\n /**\n * Project title\n */\n title: string = '';\n\n /**\n * Project description\n */\n description: string = '';\n\n /**\n * Project owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Project URL\n */\n url: string = '';\n\n /**\n * Project provider type\n */\n providerType: ProjectProviderType = 'github';\n\n /**\n * Environment variable name or config key for token resolution\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Available statuses (columns) in the project\n */\n statuses: ProjectStatus[] = [];\n\n /**\n * Custom fields defined in the project\n */\n fields: ProjectField[] = [];\n\n /**\n * Status field ID for GitHub Projects V2\n */\n statusFieldId: string = '';\n\n /**\n * Maps status name to option ID (for GitHub Projects V2)\n */\n statusOptions: Record<string, string> = {};\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached project client (not persisted)\n */\n private _client?: IProject;\n\n constructor(options: ProjectOptions = {}) {\n super(options);\n if (options.projectId !== undefined) this.projectId = options.projectId;\n if (options.projectNumber !== undefined)\n this.projectNumber = options.projectNumber;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.url !== undefined) this.url = options.url;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.statuses !== undefined) this.statuses = options.statuses;\n if (options.fields !== undefined) this.fields = options.fields;\n if (options.statusFieldId !== undefined)\n this.statusFieldId = options.statusFieldId;\n if (options.statusOptions !== undefined)\n this.statusOptions = options.statusOptions;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Get the project client, resolving token from config\n *\n * @returns Project client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IProject> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getProject({\n type: this.providerType,\n projectId: this.projectId,\n token,\n statusFieldId: this.statusFieldId || undefined,\n statusOptions:\n Object.keys(this.statusOptions).length > 0\n ? this.statusOptions\n : undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync project metadata from the provider\n *\n * @param options - Sync options\n * @returns This project with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const projectData: SDKProject = await client.getProject();\n\n // Update fields from remote\n this.title = projectData.title;\n this.description = projectData.description || '';\n this.owner = projectData.owner;\n this.url = projectData.url;\n this.statuses = projectData.statuses;\n this.fields = projectData.fields;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Add an issue or PR to this project\n *\n * @param item - Issue or PullRequest to add\n * @returns Created ProjectItem\n */\n async addItem(item: Issue | PullRequest): Promise<ProjectItem> {\n if (!item.nodeId) {\n throw new Error('Item must have a nodeId (sync the item first)');\n }\n\n const client = await this.getClient();\n return await client.addItem(item.nodeId);\n }\n\n /**\n * Remove an item from this project\n *\n * @param itemId - Project item ID to remove\n */\n async removeItem(itemId: string): Promise<void> {\n const client = await this.getClient();\n await client.removeItem(itemId);\n }\n\n /**\n * Get a specific item from the project\n *\n * @param itemId - Project item ID\n * @returns ProjectItem or null\n */\n async getItem(itemId: string): Promise<ProjectItem | null> {\n const client = await this.getClient();\n return await client.getItem(itemId);\n }\n\n /**\n * List items in this project\n *\n * @param filters - Optional filters\n * @returns Array of ProjectItems\n */\n async listItems(filters?: ItemFilters): Promise<ProjectItem[]> {\n const client = await this.getClient();\n return await client.listItems(filters);\n }\n\n /**\n * Update an item's status (column)\n *\n * @param itemId - Project item ID\n * @param status - New status name\n */\n async updateItemStatus(itemId: string, status: string): Promise<void> {\n const client = await this.getClient();\n await client.updateItemStatus(itemId, status);\n }\n\n /**\n * Update an item's custom field\n *\n * @param itemId - Project item ID\n * @param fieldId - Field ID\n * @param value - New value\n */\n async updateItemField(\n itemId: string,\n fieldId: string,\n value: unknown,\n ): Promise<void> {\n const client = await this.getClient();\n await client.updateItemField(itemId, fieldId, value);\n }\n\n /**\n * Get available statuses\n *\n * @returns Array of status definitions\n */\n async getStatuses(): Promise<ProjectStatus[]> {\n if (this.statuses.length > 0) {\n return this.statuses;\n }\n\n const client = await this.getClient();\n this.statuses = await client.listStatuses();\n await this.save();\n return this.statuses;\n }\n\n /**\n * Get available fields\n *\n * @returns Array of field definitions\n */\n async getFields(): Promise<ProjectField[]> {\n if (this.fields.length > 0) {\n return this.fields;\n }\n\n const client = await this.getClient();\n this.fields = await client.listFields();\n await this.save();\n return this.fields;\n }\n\n /**\n * Get items in a specific status/column\n *\n * @param status - Status name\n * @returns Array of ProjectItems in that status\n */\n async getItemsByStatus(status: string): Promise<ProjectItem[]> {\n return await this.listItems({ status });\n }\n\n /**\n * Move an item to a new status\n *\n * @param item - Issue or PullRequest\n * @param status - Target status name\n */\n async moveItem(item: Issue | PullRequest, status: string): Promise<void> {\n // First, find the item in the project\n const items = await this.listItems();\n const projectItem = items.find((i) => i.contentId === item.nodeId);\n\n if (!projectItem) {\n throw new Error('Item not found in project');\n }\n\n await this.updateItemStatus(projectItem.id, status);\n }\n\n /**\n * AI-powered: Analyze project health and suggest improvements\n *\n * @returns Analysis of project status\n */\n async analyzeHealth(): Promise<string> {\n const items = await this.listItems();\n const statuses = await this.getStatuses();\n\n // Count items by status\n const statusCounts: Record<string, number> = {};\n for (const status of statuses) {\n statusCounts[status.name] = items.filter(\n (i) => i.status === status.name,\n ).length;\n }\n\n return await this.do(\n `Analyze the health of this project board and suggest improvements.\n\n Project: ${this.title}\n Description: ${this.description}\n\n Item distribution by status:\n ${Object.entries(statusCounts)\n .map(([status, count]) => `- ${status}: ${count} items`)\n .join('\\n')}\n\n Total items: ${items.length}\n\n Provide:\n 1. Overall health assessment\n 2. Potential bottlenecks\n 3. Suggestions for improvement`,\n // Title/description/status counts hand-rolled above; skip do()'s\n // object-data injection so the board context is not duplicated.\n { includeData: false },\n );\n }\n\n /**\n * Get project by title\n *\n * @param title - Project title\n * @param options - Additional options\n * @returns Project or null\n */\n static async getByTitle(\n title: string,\n options: SmrtObjectOptions = {},\n ): Promise<Project | null> {\n const { ProjectCollection } = await import('../collections/Projects');\n const collection = await ProjectCollection.create(options);\n return await collection.findByTitle(title);\n }\n}\n","/**\n * ProjectCollection - Collection manager for Project objects\n *\n * Provides querying and discovery operations for Project entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Project } from '../models/Project';\nimport type { ProjectProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class ProjectCollection extends SmrtCollection<Project> {\n static readonly _itemClass = Project;\n\n /**\n * Find project by title\n *\n * @param title - Project title\n * @returns Project or null\n */\n async findByTitle(title: string): Promise<Project | null> {\n const results = await this.list({\n where: { title },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find projects by owner\n *\n * @param owner - Project owner (organization or user)\n * @returns Array of projects\n */\n async findByOwner(owner: string): Promise<Project[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find projects by provider type\n *\n * @param providerType - Provider type\n * @returns Array of projects\n */\n async findByProvider(providerType: ProjectProviderType): Promise<Project[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a project by ID\n *\n * @param projectId - Provider-specific project ID\n * @param options - Additional options for creation\n * @returns Project (existing or newly created)\n */\n async getOrCreate(\n projectId: string,\n options: {\n title?: string;\n owner?: string;\n providerType?: ProjectProviderType;\n tokenConfigKey?: string;\n statusFieldId?: string;\n statusOptions?: Record<string, string>;\n } = {},\n ): Promise<Project> {\n let project = await this.findOne({\n where: { projectId },\n });\n\n if (!project) {\n project = await this.create({\n projectId,\n title: options.title || '',\n owner: options.owner || '',\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n statusFieldId: options.statusFieldId || '',\n statusOptions: options.statusOptions || {},\n });\n await project.save();\n\n // Sync to get full project data\n await project.sync({ force: true });\n }\n\n return project;\n }\n\n /**\n * Sync all projects\n *\n * @param options - Sync options\n * @returns Array of synced projects\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Project[]> {\n const projects = await this.list({});\n const synced: Project[] = [];\n\n for (const project of projects) {\n await project.sync(options);\n synced.push(project);\n }\n\n return synced;\n }\n\n /**\n * Find projects with items in a specific status\n *\n * @param status - Status name\n * @returns Array of projects\n */\n async findWithItemsInStatus(status: string): Promise<Project[]> {\n const projects = await this.list({});\n const matching: Project[] = [];\n\n for (const project of projects) {\n try {\n const items = await project.getItemsByStatus(status);\n if (items.length > 0) {\n matching.push(project);\n }\n } catch (error) {\n // Log error and skip projects we can't access\n logger.warn(`Error accessing items for project ${project.projectId}`, {\n error: error instanceof Error ? error.message : error,\n });\n }\n }\n\n return matching;\n }\n\n /**\n * Get project statistics\n *\n * @param projectId - Project ID\n * @returns Statistics object\n */\n async getStatistics(projectId: string): Promise<{\n totalItems: number;\n itemsByStatus: Record<string, number>;\n itemsByType: Record<string, number>;\n }> {\n const project = await this.findOne({ where: { projectId } });\n if (!project) {\n throw new Error(`Project ${projectId} not found`);\n }\n\n const items = await project.listItems();\n const statuses = await project.getStatuses();\n\n const itemsByStatus: Record<string, number> = {};\n for (const status of statuses) {\n itemsByStatus[status.name] = 0;\n }\n\n const itemsByType: Record<string, number> = {\n Issue: 0,\n PullRequest: 0,\n DraftIssue: 0,\n };\n\n for (const item of items) {\n if (item.status && itemsByStatus[item.status] !== undefined) {\n itemsByStatus[item.status]++;\n }\n if (itemsByType[item.type] !== undefined) {\n itemsByType[item.type]++;\n }\n }\n\n return {\n totalItems: items.length,\n itemsByStatus,\n itemsByType,\n };\n }\n\n /**\n * Find projects by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of projects for the tenant\n */\n async findByTenant(tenantId: string): Promise<Project[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global projects (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global projects\n */\n async findGlobal(): Promise<Project[]> {\n return queryGlobal<Project>(this);\n }\n\n /**\n * Find projects for a tenant plus all global projects.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global projects\n */\n async findWithGlobals(tenantId: string): Promise<Project[]> {\n return queryWithGlobals<Project>(this, tenantId, 'Project.findWithGlobals');\n }\n}\n","/**\n * PullRequestCollection - Collection manager for PullRequest objects\n *\n * Provides querying and discovery operations for PullRequest entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { PullRequest } from '../models/PullRequest';\nimport type { Repository } from '../models/Repository';\nimport type { SDKPullRequest, SearchFilters } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class PullRequestCollection extends SmrtCollection<PullRequest> {\n static readonly _itemClass = PullRequest;\n\n /**\n * Discover pull requests from a repository and sync to database\n *\n * @param options - Discovery options\n * @returns Array of PullRequest objects\n */\n async discover(options: {\n repository: Repository;\n filters?: SearchFilters;\n }): Promise<PullRequest[]> {\n const { repository, filters } = options;\n const repositoryId = repository.id ?? undefined;\n\n if (!repositoryId) {\n throw new Error(\n 'Repository must be saved before discovering pull requests',\n );\n }\n\n const repoClient = await repository.getClient();\n\n // Note: searchIssues with type filter would get PRs in GitHub\n // For now, we'll search for all and filter\n const remoteItems = await repoClient.searchIssues('is:pr', filters);\n\n const pullRequests: PullRequest[] = [];\n\n for (const remote of remoteItems) {\n // Get full PR data\n let prData: SDKPullRequest;\n try {\n prData = await repoClient.getPullRequest(remote.number);\n } catch (error) {\n // Log error and skip PR - could be rate limiting, auth, or access issues\n logger.warn(\n `Failed to fetch PR #${remote.number} from ${repository.owner}/${repository.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n continue;\n }\n\n // Find existing PR by repository + number\n let pr = await this.findOne({\n where: {\n repositoryId,\n number: remote.number,\n },\n });\n\n if (!pr) {\n // Create new PR\n pr = await this.create({\n repositoryId,\n number: prData.number,\n nodeId: prData.id,\n title: prData.title,\n body: prData.body,\n state: prData.state,\n author: prData.author.login,\n labels: prData.labels.map((l) => l.name),\n assignees: prData.assignees.map((a) => a.login),\n commentsCount: prData.commentsCount,\n headRef: prData.headRef,\n baseRef: prData.baseRef,\n merged: prData.merged,\n mergedAt: prData.mergedAt || null,\n mergeable: prData.mergeable,\n draft: prData.draft,\n lastSyncedAt: new Date(),\n });\n } else {\n // Update existing PR\n pr.nodeId = prData.id;\n pr.title = prData.title;\n pr.body = prData.body;\n pr.state = prData.state;\n pr.author = prData.author.login;\n pr.labels = prData.labels.map((l) => l.name);\n pr.assignees = prData.assignees.map((a) => a.login);\n pr.commentsCount = prData.commentsCount;\n pr.headRef = prData.headRef;\n pr.baseRef = prData.baseRef;\n pr.merged = prData.merged;\n pr.mergedAt = prData.mergedAt || null;\n pr.mergeable = prData.mergeable;\n pr.draft = prData.draft;\n pr.lastSyncedAt = new Date();\n }\n\n await pr.save();\n pullRequests.push(pr);\n }\n\n return pullRequests;\n }\n\n /**\n * Find PRs by repository\n *\n * @param repositoryId - Repository ID\n * @returns Array of PRs\n */\n async findByRepository(repositoryId: string): Promise<PullRequest[]> {\n return await this.list({\n where: { repositoryId },\n });\n }\n\n /**\n * Find open PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of open PRs\n */\n async findOpen(repositoryId?: string): Promise<PullRequest[]> {\n const where: Record<string, unknown> = { state: 'open' };\n if (repositoryId) {\n where.repositoryId = repositoryId;\n }\n return await this.list({ where });\n }\n\n /**\n * Find draft PRs\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of draft PRs\n */\n async findDrafts(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => pr.draft);\n }\n\n /**\n * Find PRs ready to merge\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of mergeable PRs\n */\n async findReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n return openPRs.filter((pr) => !pr.draft && pr.mergeable);\n }\n\n /**\n * Find PRs by branch\n *\n * @param branch - Branch name (head or base)\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findByBranch(\n branch: string,\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.list({\n where: repositoryId ? { repositoryId } : {},\n });\n\n return prs.filter((pr) => pr.headRef === branch || pr.baseRef === branch);\n }\n\n /**\n * Find PR by number in a repository\n *\n * @param repositoryId - Repository ID\n * @param number - PR number\n * @returns PullRequest or null\n */\n async findByNumber(\n repositoryId: string,\n number: number,\n ): Promise<PullRequest | null> {\n const results = await this.list({\n where: { repositoryId, number },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find PRs ready to merge (AI-powered)\n *\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs that are ready\n */\n async findAIReadyToMerge(repositoryId?: string): Promise<PullRequest[]> {\n const openPRs = await this.findOpen(repositoryId);\n const ready: PullRequest[] = [];\n\n for (const pr of openPRs) {\n if (await pr.isReadyToMerge()) {\n ready.push(pr);\n }\n }\n\n return ready;\n }\n\n /**\n * Get PRs by change size\n *\n * @param size - Size classification\n * @param repositoryId - Optional repository filter\n * @returns Array of PRs\n */\n async findBySize(\n size: 'xs' | 's' | 'm' | 'l' | 'xl',\n repositoryId?: string,\n ): Promise<PullRequest[]> {\n const prs = await this.findOpen(repositoryId);\n return prs.filter((pr) => pr.getChangeSize() === size);\n }\n\n /**\n * Batch sync PRs from repository\n *\n * @param repository - Repository to sync from\n * @param options - Sync options\n * @returns Array of synced PRs\n */\n async batchSync(\n repository: Repository,\n options: { force?: boolean } = {},\n ): Promise<PullRequest[]> {\n const prs = await this.findByRepository(repository.id as string);\n const synced: PullRequest[] = [];\n\n for (const pr of prs) {\n await pr.sync(options);\n synced.push(pr);\n }\n\n return synced;\n }\n\n /**\n * Find pull requests by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of pull requests for the tenant\n */\n async findByTenant(tenantId: string): Promise<PullRequest[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global pull requests (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global pull requests\n */\n async findGlobal(): Promise<PullRequest[]> {\n return queryGlobal<PullRequest>(this);\n }\n\n /**\n * Find pull requests for a tenant plus all global pull requests.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global pull requests\n */\n async findWithGlobals(tenantId: string): Promise<PullRequest[]> {\n return queryWithGlobals<PullRequest>(\n this,\n tenantId,\n 'PullRequest.findWithGlobals',\n );\n }\n}\n","/**\n * Repository model - SMRT wrapper for repository operations\n *\n * Provides persistent repository tracking with provider-agnostic operations.\n * Uses @happyvertical/repos SDK for actual API calls.\n */\n\nimport { getRepository } from '@happyvertical/repos';\nimport { getModuleConfig } from '@happyvertical/smrt-config';\nimport {\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SYNC_THROTTLE_MS } from '../constants';\nimport type {\n CreateIssueInput,\n CreatePRInput,\n IRepository,\n RepositoryProviderType,\n SDKRepository,\n SearchFilters,\n SyncOptions,\n} from '../types';\nimport type { Issue } from './Issue';\nimport type { PullRequest } from './PullRequest';\n\nexport interface RepositoryOptions extends SmrtObjectOptions {\n owner?: string;\n name?: string;\n fullName?: string;\n description?: string;\n defaultBranch?: string;\n isPrivate?: boolean;\n providerType?: RepositoryProviderType;\n baseUrl?: string;\n tokenConfigKey?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'sync'] },\n // sync is an operator command invoked in-process via the CLI;\n // it intentionally isn't exposed over HTTP today.\n cli: { include: ['list', 'get', 'sync', 'create'], skipApiCheck: true },\n})\nexport class Repository extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Repository owner (organization or user)\n */\n owner: string = '';\n\n /**\n * Repository name\n */\n name: string = '';\n\n /**\n * Full name in owner/repo format\n */\n fullName: string = '';\n\n /**\n * Repository description\n */\n description: string = '';\n\n /**\n * Default branch name\n */\n defaultBranch: string = 'main';\n\n /**\n * Whether repository is private\n */\n isPrivate: boolean = false;\n\n /**\n * Repository provider type\n */\n providerType: RepositoryProviderType = 'github';\n\n /**\n * Base URL for self-hosted instances (GitHub Enterprise, GitLab self-hosted, etc.)\n */\n baseUrl: string = '';\n\n /**\n * Environment variable name or config key for token resolution\n * The token is NOT stored - only the key name is persisted\n */\n tokenConfigKey: string = 'GITHUB_TOKEN';\n\n /**\n * Last sync timestamp\n */\n lastSyncedAt: Date | null = null;\n\n /**\n * Transient: Cached repository client (not persisted)\n */\n private _client?: IRepository;\n\n constructor(options: RepositoryOptions = {}) {\n super(options);\n if (options.owner !== undefined) this.owner = options.owner;\n if (options.name !== undefined) this.name = options.name;\n if (options.fullName !== undefined) this.fullName = options.fullName;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.defaultBranch !== undefined)\n this.defaultBranch = options.defaultBranch;\n if (options.isPrivate !== undefined) this.isPrivate = options.isPrivate;\n if (options.providerType !== undefined)\n this.providerType = options.providerType;\n if (options.baseUrl !== undefined) this.baseUrl = options.baseUrl;\n if (options.tokenConfigKey !== undefined)\n this.tokenConfigKey = options.tokenConfigKey;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Get the repository client, resolving token from config\n *\n * Token resolution order:\n * 1. Environment variable matching tokenConfigKey\n * 2. Module config value matching tokenConfigKey\n *\n * @returns Repository client for API operations\n * @throws Error if token cannot be resolved\n */\n async getClient(): Promise<IRepository> {\n if (this._client) {\n return this._client;\n }\n\n // Resolve token from environment or config\n const token =\n process.env[this.tokenConfigKey] ||\n (getModuleConfig<Record<string, string>>('smrt-projects', {})[\n this.tokenConfigKey\n ] as string);\n\n if (!token) {\n throw new Error(\n `Token not found for key '${this.tokenConfigKey}'. ` +\n `Set the ${this.tokenConfigKey} environment variable or configure it in smrt.config.`,\n );\n }\n\n this._client = await getRepository({\n type: this.providerType,\n owner: this.owner,\n repo: this.name,\n token,\n baseUrl: this.baseUrl || undefined,\n });\n\n return this._client;\n }\n\n /**\n * Clear the cached client (useful after token refresh)\n */\n clearClient(): void {\n this._client = undefined;\n }\n\n /**\n * Sync repository metadata from the provider\n *\n * @param options - Sync options\n * @returns This repository with updated fields\n */\n async sync(options: SyncOptions = {}): Promise<this> {\n // Check if we recently synced (within 5 minutes)\n if (\n !options.force &&\n this.lastSyncedAt &&\n Date.now() - this.lastSyncedAt.getTime() < SYNC_THROTTLE_MS\n ) {\n return this;\n }\n\n const client = await this.getClient();\n const repoData: SDKRepository = await client.getRepository();\n\n // Update fields from remote\n this.owner = repoData.owner;\n this.name = repoData.name;\n this.fullName = `${repoData.owner}/${repoData.name}`;\n this.description = repoData.description;\n this.defaultBranch = repoData.defaultBranch;\n this.isPrivate = repoData.isPrivate;\n this.lastSyncedAt = new Date();\n\n await this.save();\n return this;\n }\n\n /**\n * Get issues from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of Issue objects (SMRT models)\n */\n async getIssues(filters?: SearchFilters): Promise<Issue[]> {\n const { IssueCollection } = await import('../collections/Issues');\n const collection = await IssueCollection.create(this.options);\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Get pull requests from this repository\n *\n * @param filters - Optional search filters\n * @returns Array of PullRequest objects (SMRT models)\n */\n async getPullRequests(filters?: SearchFilters): Promise<PullRequest[]> {\n const { PullRequestCollection } = await import(\n '../collections/PullRequests'\n );\n const collection = await PullRequestCollection.create(this.options);\n return await collection.discover({ repository: this, filters });\n }\n\n /**\n * Create a new issue in this repository\n *\n * @param data - Issue creation data\n * @returns Created Issue (SMRT model)\n */\n async createIssue(data: CreateIssueInput): Promise<Issue> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating issues');\n }\n\n const client = await this.getClient();\n const created = await client.createIssue(data);\n\n // Create SMRT Issue from remote data\n const { Issue } = await import('./Issue');\n const issue = new Issue({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n lastSyncedAt: new Date(),\n });\n\n // Directly-constructed models must be initialized before save() can access\n // the database connection (SmrtCollection.create() does this internally).\n await issue.initialize();\n await issue.save();\n return issue;\n }\n\n /**\n * Create a new pull request in this repository\n *\n * @param data - PR creation data\n * @returns Created PullRequest (SMRT model)\n */\n async createPullRequest(data: CreatePRInput): Promise<PullRequest> {\n const repositoryId = this.id ?? undefined;\n if (!repositoryId) {\n throw new Error('Repository must be saved before creating pull requests');\n }\n\n const client = await this.getClient();\n const created = await client.createPullRequest(data);\n\n // Create SMRT PullRequest from remote data\n const { PullRequest } = await import('./PullRequest');\n const pr = new PullRequest({\n ...this.options,\n repositoryId,\n number: created.number,\n nodeId: created.id,\n title: created.title,\n body: created.body,\n state: created.state,\n author: created.author.login,\n labels: created.labels.map((l) => l.name),\n assignees: created.assignees.map((a) => a.login),\n commentsCount: created.commentsCount,\n headRef: created.headRef,\n baseRef: created.baseRef,\n merged: created.merged,\n draft: created.draft,\n lastSyncedAt: new Date(),\n });\n\n // Directly-constructed models must be initialized before save() can access\n // the database connection (SmrtCollection.create() does this internally).\n await pr.initialize();\n await pr.save();\n return pr;\n }\n\n /**\n * Check if this repository has any open issues matching criteria\n *\n * @param criteria - Natural language description of what to check\n * @returns True if matching issues exist\n */\n async hasOpenIssuesMatching(criteria: string): Promise<boolean> {\n const issues = await this.getIssues({ state: 'open' });\n if (issues.length === 0) return false;\n\n return await this.is(\n `This repository has open issues matching: ${criteria}. ` +\n `Current open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}`,\n );\n }\n\n /**\n * Generate a summary of repository activity\n *\n * @returns AI-generated summary\n */\n async summarizeActivity(): Promise<string> {\n const issues = await this.getIssues({ state: 'open', limit: 10 });\n const prs = await this.getPullRequests({ state: 'open', limit: 10 });\n\n return await this.do(\n `Summarize the current activity in this repository. ` +\n `Open issues: ${issues.map((i) => `#${i.number}: ${i.title}`).join(', ')}. ` +\n `Open PRs: ${prs.map((p) => `#${p.number}: ${p.title}`).join(', ')}.`,\n );\n }\n\n /**\n * Get repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options\n * @returns Repository or null if not found\n */\n static async getByFullName(\n owner: string,\n name: string,\n options: SmrtObjectOptions = {},\n ): Promise<Repository | null> {\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await RepositoryCollection.create(options);\n return await collection.findByFullName(owner, name);\n }\n}\n","/**\n * RepositoryCollection - Collection manager for Repository objects\n *\n * Provides querying and discovery operations for Repository entities.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Repository } from '../models/Repository';\nimport type { RepositoryProviderType } from '../types';\n\nconst logger = createLogger({ level: 'info' });\n\nexport class RepositoryCollection extends SmrtCollection<Repository> {\n static readonly _itemClass = Repository;\n\n /**\n * Find a repository by owner and name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @returns Repository or null\n */\n async findByFullName(\n owner: string,\n name: string,\n ): Promise<Repository | null> {\n const results = await this.list({\n where: { owner, name },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find repositories by owner\n *\n * @param owner - Repository owner\n * @returns Array of repositories\n */\n async findByOwner(owner: string): Promise<Repository[]> {\n return await this.list({\n where: { owner },\n });\n }\n\n /**\n * Find repositories by provider type\n *\n * @param providerType - Provider type\n * @returns Array of repositories\n */\n async findByProvider(\n providerType: RepositoryProviderType,\n ): Promise<Repository[]> {\n return await this.list({\n where: { providerType },\n });\n }\n\n /**\n * Get or create a repository by owner/name\n *\n * @param owner - Repository owner\n * @param name - Repository name\n * @param options - Additional options for creation\n * @returns Repository (existing or newly created)\n */\n async getOrCreate(\n owner: string,\n name: string,\n options: {\n providerType?: RepositoryProviderType;\n tokenConfigKey?: string;\n baseUrl?: string;\n } = {},\n ): Promise<Repository> {\n let repo = await this.findByFullName(owner, name);\n\n if (!repo) {\n repo = await this.create({\n owner,\n name,\n fullName: `${owner}/${name}`,\n providerType: options.providerType || 'github',\n tokenConfigKey: options.tokenConfigKey || 'GITHUB_TOKEN',\n baseUrl: options.baseUrl || '',\n });\n await repo.save();\n }\n\n return repo;\n }\n\n /**\n * Sync all repositories\n *\n * @param options - Sync options\n * @returns Array of synced repositories\n */\n async syncAll(options: { force?: boolean } = {}): Promise<Repository[]> {\n const repos = await this.list({});\n const synced: Repository[] = [];\n\n for (const repo of repos) {\n await repo.sync(options);\n synced.push(repo);\n }\n\n return synced;\n }\n\n /**\n * Find repositories with open issues\n *\n * @returns Array of repositories with at least one open issue\n */\n async findWithOpenIssues(): Promise<Repository[]> {\n const repos = await this.list({});\n const withIssues: Repository[] = [];\n\n for (const repo of repos) {\n try {\n const issues = await repo.getIssues({ state: 'open', limit: 1 });\n if (issues.length > 0) {\n withIssues.push(repo);\n }\n } catch (error) {\n // Log error and skip repos we can't access\n logger.warn(\n `Error accessing issues for repository ${repo.owner}/${repo.name}`,\n { error: error instanceof Error ? error.message : error },\n );\n }\n }\n\n return withIssues;\n }\n\n /**\n * Find repositories by tenant ID\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of repositories for the tenant\n */\n async findByTenant(tenantId: string): Promise<Repository[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global repositories (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global repositories\n */\n async findGlobal(): Promise<Repository[]> {\n return queryGlobal<Repository>(this);\n }\n\n /**\n * Find repositories for a tenant plus all global repositories.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID to filter by\n * @returns Array of tenant and global repositories\n */\n async findWithGlobals(tenantId: string): Promise<Repository[]> {\n return queryWithGlobals<Repository>(\n this,\n tenantId,\n 'Repository.findWithGlobals',\n );\n }\n}\n","/**\n * Comment model - SMRT wrapper for issue/PR comments\n *\n * Represents a comment on an issue or pull request.\n */\n\nimport { createLogger } from '@happyvertical/logger';\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nconst logger = createLogger({ level: 'info' });\n\nexport interface CommentOptions extends SmrtObjectOptions {\n issueId?: string;\n commentId?: string;\n body?: string;\n author?: string;\n createdAt?: Date;\n updatedAt?: Date;\n url?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class Comment extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Issue this comment belongs to\n */\n @foreignKey('Issue')\n issueId?: string;\n\n /**\n * Provider-specific comment ID\n */\n commentId: string = '';\n\n /**\n * Comment body text\n */\n body: string = '';\n\n /**\n * Comment author's login\n */\n author: string = '';\n\n /**\n * When the comment was created\n */\n createdAt: Date | null = null;\n\n /**\n * When the comment was last updated\n */\n updatedAt: Date | null = null;\n\n /**\n * Comment URL\n */\n url: string = '';\n\n constructor(options: CommentOptions = {}) {\n super(options);\n if (options.issueId !== undefined) this.issueId = options.issueId;\n if (options.commentId !== undefined) this.commentId = options.commentId;\n if (options.body !== undefined) this.body = options.body;\n if (options.author !== undefined) this.author = options.author;\n if (options.createdAt !== undefined) this.createdAt = options.createdAt;\n if (options.updatedAt !== undefined) this.updatedAt = options.updatedAt;\n if (options.url !== undefined) this.url = options.url;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * AI-powered: Check if this comment contains a question\n */\n async isQuestion(): Promise<boolean> {\n return await this.is(\n 'This comment contains a question or request for clarification',\n );\n }\n\n /**\n * AI-powered: Check if this comment contains approval\n */\n async isApproval(): Promise<boolean> {\n return await this.is(\n 'This comment expresses approval, agreement, or a positive response (LGTM, +1, approved, etc.)',\n );\n }\n\n /**\n * AI-powered: Check if this comment requests changes\n */\n async requestsChanges(): Promise<boolean> {\n return await this.is(\n 'This comment requests changes, modifications, or improvements to the issue/PR',\n );\n }\n\n /**\n * AI-powered: Extract action items from this comment\n *\n * @returns Array of action items\n */\n async extractActionItems(): Promise<string[]> {\n const result = await this.do(\n `Extract any action items, tasks, or requests from this comment.\n Return a JSON array of strings, each representing one action item.\n If no action items, return an empty array [].\n Only return the JSON array, nothing else.\n\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n try {\n return JSON.parse(result);\n } catch (error) {\n logger.warn('Failed to parse action items JSON', {\n error: error instanceof Error ? error.message : error,\n response: result,\n });\n return [];\n }\n }\n\n /**\n * AI-powered: Summarize this comment\n *\n * @returns Brief summary\n */\n async summarize(): Promise<string> {\n return await this.do(\n `Summarize this comment in one sentence.\n Comment by ${this.author}: ${this.body}`,\n // Author + body hand-rolled above; skip do()'s object-data injection.\n { includeData: false },\n );\n }\n\n /**\n * Get the sentiment of this comment\n *\n * @returns Sentiment classification\n */\n async getSentiment(): Promise<'positive' | 'negative' | 'neutral'> {\n const result = await this.do(\n `Classify the sentiment of this comment as exactly one of: positive, negative, neutral\n Only return one word.\n Comment: ${this.body}`,\n // Body is hand-rolled above; skip do()'s object-data injection (no dup).\n { includeData: false },\n );\n\n const normalized = result.toLowerCase().trim();\n if (normalized.includes('positive')) return 'positive';\n if (normalized.includes('negative')) return 'negative';\n return 'neutral';\n }\n}\n","/**\n * Label model - SMRT wrapper for repository labels\n *\n * Represents a label that can be applied to issues and PRs.\n */\n\nimport {\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\nexport interface LabelOptions extends SmrtObjectOptions {\n repositoryId?: string;\n name?: string;\n color?: string;\n description?: string;\n}\n\n@smrt({\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: { include: ['list', 'get', 'create', 'update', 'delete'] },\n})\nexport class Label extends SmrtObject {\n /**\n * Repository this label belongs to\n */\n @foreignKey('Repository')\n repositoryId?: string;\n\n /**\n * Label name\n */\n name: string = '';\n\n /**\n * Label color (hex without #)\n */\n color: string = '';\n\n /**\n * Label description\n */\n description: string = '';\n\n constructor(options: LabelOptions = {}) {\n super(options);\n if (options.repositoryId !== undefined)\n this.repositoryId = options.repositoryId;\n if (options.name !== undefined) this.name = options.name;\n if (options.color !== undefined) this.color = options.color;\n if (options.description !== undefined)\n this.description = options.description;\n }\n\n /**\n * Check if this is a type label (bug, feature, etc.)\n */\n isTypeLabel(): boolean {\n const typePatterns = [\n /^type:/i,\n /^kind:/i,\n /^bug$/i,\n /^feature$/i,\n /^enhancement$/i,\n /^docs$/i,\n /^chore$/i,\n ];\n return typePatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a priority label\n */\n isPriorityLabel(): boolean {\n const priorityPatterns = [\n /^p[0-4]$/i,\n /^priority:/i,\n /^critical$/i,\n /^high$/i,\n /^medium$/i,\n /^low$/i,\n ];\n return priorityPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Check if this is a status label\n */\n isStatusLabel(): boolean {\n const statusPatterns = [\n /^status:/i,\n /^wip$/i,\n /^in.?progress$/i,\n /^blocked$/i,\n /^needs.?review$/i,\n /^ready$/i,\n ];\n return statusPatterns.some((p) => p.test(this.name));\n }\n\n /**\n * Get the label category\n *\n * @returns Category name\n */\n getCategory(): 'type' | 'priority' | 'status' | 'area' | 'other' {\n if (this.isTypeLabel()) return 'type';\n if (this.isPriorityLabel()) return 'priority';\n if (this.isStatusLabel()) return 'status';\n if (this.name.includes(':')) return 'area';\n return 'other';\n }\n\n /**\n * Parse priority level from label name\n *\n * @returns Priority level 0-4 or null\n */\n getPriorityLevel(): number | null {\n const match = this.name.match(/p([0-4])/i);\n if (match) {\n return parseInt(match[1], 10);\n }\n if (/critical/i.test(this.name)) return 0;\n if (/high/i.test(this.name)) return 1;\n if (/medium/i.test(this.name)) return 2;\n if (/low/i.test(this.name)) return 3;\n return null;\n }\n\n /**\n * Get label with # prefix for hex color\n */\n getHexColor(): string {\n return this.color.startsWith('#') ? this.color : `#${this.color}`;\n }\n\n /**\n * Create a label in the repository\n */\n async createInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await RepositoryCollection.create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.createLabel({\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n\n /**\n * Update this label in the repository\n */\n async updateInRepository(): Promise<void> {\n if (!this.repositoryId) {\n throw new Error('Label must have a repositoryId');\n }\n\n const { RepositoryCollection } = await import(\n '../collections/Repositories'\n );\n const collection = await RepositoryCollection.create(this.options);\n const repo = await collection.get({ id: this.repositoryId });\n\n if (!repo) {\n throw new Error(`Repository ${this.repositoryId} not found`);\n }\n\n const client = await repo.getClient();\n await client.updateLabel(this.name, {\n name: this.name,\n color: this.color,\n description: this.description,\n });\n\n await this.save();\n }\n}\n"],"mappings":"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"}
|
package/dist/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0.0",
|
|
3
|
-
"timestamp":
|
|
3
|
+
"timestamp": 1782953437885,
|
|
4
4
|
"packageName": "@happyvertical/smrt-projects",
|
|
5
|
-
"packageVersion": "0.37.
|
|
5
|
+
"packageVersion": "0.37.5",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-projects:IssueCollection": {
|
|
8
8
|
"name": "issuecollection",
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-07-
|
|
3
|
+
"generatedAt": "2026-07-02T00:50:38.308Z",
|
|
4
4
|
"packageName": "@happyvertical/smrt-projects",
|
|
5
|
-
"packageVersion": "0.37.
|
|
5
|
+
"packageVersion": "0.37.5",
|
|
6
6
|
"sourceManifestPath": "dist/manifest.json",
|
|
7
7
|
"agentDocPath": "AGENTS.md",
|
|
8
8
|
"sourceHashes": {
|
|
9
|
-
"manifest": "
|
|
10
|
-
"packageJson": "
|
|
9
|
+
"manifest": "b3ee495b667755e31b2ceca9f195560310cf1b3126a015e715a873f466986f96",
|
|
10
|
+
"packageJson": "41ed95093018fba440535d3cf249e65fe5b3c7e515fd4b3468b5a07bb209c81a",
|
|
11
11
|
"agents": "31de38c962634d69c728bab8dff270448a49718fc36ee20b9cd12216cdbed95c"
|
|
12
12
|
},
|
|
13
13
|
"exports": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-projects",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.5",
|
|
4
4
|
"description": "Provider-agnostic project management models (Issues, PRs, Repositories, Projects) for SMRT framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"smrtRawPrimitives": "strict",
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"@happyvertical/repos": "^0.74.11",
|
|
40
40
|
"@happyvertical/sql": "^0.74.11",
|
|
41
41
|
"@happyvertical/utils": "^0.74.11",
|
|
42
|
-
"@happyvertical/smrt-config": "0.37.
|
|
43
|
-
"@happyvertical/smrt-core": "0.37.
|
|
44
|
-
"@happyvertical/smrt-prompts": "0.37.
|
|
45
|
-
"@happyvertical/smrt-tenancy": "0.37.
|
|
46
|
-
"@happyvertical/smrt-types": "0.37.
|
|
47
|
-
"@happyvertical/smrt-ui": "0.37.
|
|
42
|
+
"@happyvertical/smrt-config": "0.37.5",
|
|
43
|
+
"@happyvertical/smrt-core": "0.37.5",
|
|
44
|
+
"@happyvertical/smrt-prompts": "0.37.5",
|
|
45
|
+
"@happyvertical/smrt-tenancy": "0.37.5",
|
|
46
|
+
"@happyvertical/smrt-types": "0.37.5",
|
|
47
|
+
"@happyvertical/smrt-ui": "0.37.5"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"svelte": "^5.56.4"
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"typescript": "^5.9.3",
|
|
65
65
|
"vite": "^8.1.2",
|
|
66
66
|
"vitest": "^4.1.9",
|
|
67
|
-
"@happyvertical/smrt-cli": "0.37.
|
|
68
|
-
"@happyvertical/smrt-vitest": "0.37.
|
|
67
|
+
"@happyvertical/smrt-cli": "0.37.5",
|
|
68
|
+
"@happyvertical/smrt-vitest": "0.37.5"
|
|
69
69
|
},
|
|
70
70
|
"keywords": [
|
|
71
71
|
"ai",
|