memory-journal-mcp 7.1.0 → 7.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -51
- package/dist/{chunk-GW5DYUQJ.js → chunk-GR4T3SRW.js} +139 -100
- package/dist/{chunk-37BQOJDZ.js → chunk-IWKLHSPU.js} +81 -2
- package/dist/{chunk-JEGRDY6W.js → chunk-ORV7ZZOE.js} +357 -51
- package/dist/cli.js +30 -4
- package/dist/github-integration-2TFMXHIJ.js +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -3
- package/dist/{tools-O44Q52RD.js → tools-CXR2FEB2.js} +2 -2
- package/package.json +1 -1
- package/skills/README.md +77 -0
- package/skills/autonomous-dev/SKILL.md +56 -0
- package/skills/bin/sync.js +50 -0
- package/skills/bun/SKILL.md +156 -0
- package/skills/github-commander/SKILL.md +1 -1
- package/skills/github-commander/workflows/code-quality-audit.md +7 -5
- package/skills/github-commander/workflows/issue-triage.md +13 -4
- package/skills/github-commander/workflows/milestone-sprint.md +9 -1
- package/skills/github-commander/workflows/perf-audit.md +2 -0
- package/skills/github-commander/workflows/pr-review.md +9 -3
- package/skills/github-commander/workflows/roadmap-kickoff.md +79 -0
- package/skills/github-commander/workflows/security-audit.md +3 -3
- package/skills/github-commander/workflows/update-deps.md +2 -2
- package/skills/gitlab/SKILL.md +115 -0
- package/skills/gitlab/package-lock.json +392 -0
- package/skills/gitlab/package.json +14 -0
- package/skills/gitlab/scripts/gitlab-client.ts +125 -0
- package/skills/gitlab/scripts/gitlab-helper.ts +80 -0
- package/skills/golang/SKILL.md +54 -0
- package/skills/mysql/SKILL.md +30 -0
- package/skills/package.json +48 -0
- package/skills/playwright-standard/SKILL.md +58 -0
- package/skills/playwright-standard/examples/fixtures.ts +66 -0
- package/skills/playwright-standard/examples/type-stubs.d.ts +10 -0
- package/skills/playwright-standard/references/advanced-scenarios.md +59 -0
- package/skills/playwright-standard/references/infrastructure.md +43 -0
- package/skills/postgres/SKILL.md +33 -0
- package/skills/react-best-practices/AGENTS.md +2883 -0
- package/skills/react-best-practices/README.md +127 -0
- package/skills/react-best-practices/SKILL.md +138 -0
- package/skills/react-best-practices/metadata.json +17 -0
- package/skills/react-best-practices/rules/_sections.md +46 -0
- package/skills/react-best-practices/rules/_template.md +28 -0
- package/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/react-best-practices/rules/async-api-routes.md +35 -0
- package/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/skills/react-best-practices/rules/async-dependencies.md +48 -0
- package/skills/react-best-practices/rules/async-parallel.md +24 -0
- package/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skills/react-best-practices/rules/bundle-conditional.md +37 -0
- package/skills/react-best-practices/rules/bundle-defer-third-party.md +48 -0
- package/skills/react-best-practices/rules/bundle-dynamic-imports.md +34 -0
- package/skills/react-best-practices/rules/bundle-preload.md +44 -0
- package/skills/react-best-practices/rules/client-event-listeners.md +78 -0
- package/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
- package/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
- package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/react-best-practices/rules/js-cache-storage.md +68 -0
- package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/react-best-practices/rules/js-length-check-first.md +50 -0
- package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/react-best-practices/rules/rendering-activity.md +24 -0
- package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
- package/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
- package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
- package/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +72 -0
- package/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +26 -0
- package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
- package/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
- package/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
- package/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/rust/SKILL.md +86 -0
- package/skills/shadcn-ui/SKILL.md +72 -0
- package/skills/skill-builder/SKILL.md +457 -0
- package/skills/skill-builder/checklist.md +65 -0
- package/skills/sqlite/SKILL.md +38 -0
- package/skills/typescript/SKILL.md +453 -0
- package/skills/typescript/assets/eslint-template.js +102 -0
- package/skills/typescript/assets/tsconfig-template.json +45 -0
- package/skills/typescript/references/enterprise-patterns.md +531 -0
- package/skills/typescript/references/generics.md +493 -0
- package/skills/typescript/references/nestjs-integration.md +579 -0
- package/skills/typescript/references/react-integration.md +616 -0
- package/skills/typescript/references/toolchain.md +547 -0
- package/skills/typescript/references/type-system.md +481 -0
- package/skills/vitest-standard/SKILL.md +82 -0
- package/skills/vitest-standard/examples/service-mock.ts +60 -0
- package/skills/vitest-standard/examples/tdd-calculator.ts +41 -0
- package/skills/vitest-standard/examples/type-stubs.d.ts +18 -0
- package/skills/vitest-standard/references/async-and-errors.md +58 -0
- package/skills/vitest-standard/references/coverage-and-config.md +53 -0
- package/skills/vitest-standard/references/mocking.md +61 -0
- package/skills/vitest-standard/references/tdd-patterns.md +60 -0
- package/dist/github-integration-FOJ4U6I5.js +0 -1
- package/skills/github-commander/workflows/full-audit.md +0 -134
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { withSessionInit, withPriority, ASSISTANT_FOCUSED, TOOL_GROUPS, HIGH_PRIORITY, LOW_PRIORITY, MEDIUM_PRIORITY, setDefaultSandboxMode, initializeAuditLogger, parseToolFilter, getFilterSummary, getToolFilterFromEnv, getTools, getEnabledGroups, callTool, getGlobalAuditLogger, sendProgress, SUPPORTED_SCOPES, getRequiredScope, hasScope, getAuditResourceDef, execQuery, transformEntryRow, resolveGitHubRepo, isResourceError, milestoneCompletionPct, parseScopes, BASE_SCOPES, getAllToolNames, globalMetrics, DEFAULT_BRIEFING_CONFIG } from './chunk-
|
|
2
|
-
import { logger, GitHubIntegration, ConfigurationError, ResourceNotFoundError, ConnectionError, QueryError, assertNoPathTraversal, ValidationError, MemoryJournalMcpError, validateDateFormatPattern } from './chunk-
|
|
1
|
+
import { withSessionInit, withPriority, ASSISTANT_FOCUSED, TOOL_GROUPS, HIGH_PRIORITY, LOW_PRIORITY, MEDIUM_PRIORITY, setDefaultSandboxMode, initializeAuditLogger, parseToolFilter, getFilterSummary, getToolFilterFromEnv, getTools, getEnabledGroups, callTool, getGlobalAuditLogger, sendProgress, SUPPORTED_SCOPES, getRequiredScope, hasScope, getAuditResourceDef, execQuery, transformEntryRow, resolveGitHubRepo, isResourceError, milestoneCompletionPct, parseScopes, BASE_SCOPES, getAllToolNames, globalMetrics, DEFAULT_BRIEFING_CONFIG } from './chunk-ORV7ZZOE.js';
|
|
2
|
+
import { logger, GitHubIntegration, ConfigurationError, ResourceNotFoundError, ConnectionError, QueryError, assertNoPathTraversal, ValidationError, MemoryJournalMcpError, validateDateFormatPattern } from './chunk-IWKLHSPU.js';
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
4
|
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
5
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -1828,7 +1828,7 @@ async function buildGitHubSection(github, config) {
|
|
|
1828
1828
|
const [ciStatus, issuesAndPrs, milestones, insights, copilotReviews] = await Promise.all([
|
|
1829
1829
|
fetchCiStatus(github, owner, repo, config),
|
|
1830
1830
|
fetchIssuesAndPrs(github, owner, repo, config),
|
|
1831
|
-
fetchMilestones(github, owner, repo),
|
|
1831
|
+
fetchMilestones(github, owner, repo, config.milestoneCount ?? 3),
|
|
1832
1832
|
fetchInsights(github, owner, repo),
|
|
1833
1833
|
config.copilotReviews ? fetchCopilotReviews(github, owner, repo) : Promise.resolve(void 0)
|
|
1834
1834
|
]);
|
|
@@ -1959,9 +1959,10 @@ async function fetchIssuesAndPrs(github, owner, repo, config) {
|
|
|
1959
1959
|
return { openIssues: 0, openPRs: 0 };
|
|
1960
1960
|
}
|
|
1961
1961
|
}
|
|
1962
|
-
async function fetchMilestones(github, owner, repo) {
|
|
1962
|
+
async function fetchMilestones(github, owner, repo, limit) {
|
|
1963
|
+
if (limit <= 0) return [];
|
|
1963
1964
|
try {
|
|
1964
|
-
const msList = await github.getMilestones(owner, repo, "open",
|
|
1965
|
+
const msList = await github.getMilestones(owner, repo, "open", limit);
|
|
1965
1966
|
return msList.map((m) => {
|
|
1966
1967
|
const pct = milestoneCompletionPct(m.openIssues, m.closedIssues);
|
|
1967
1968
|
return {
|
|
@@ -2039,8 +2040,8 @@ async function fetchCopilotReviews(github, owner, repo) {
|
|
|
2039
2040
|
}
|
|
2040
2041
|
}
|
|
2041
2042
|
var PREVIEW_LENGTH = 80;
|
|
2042
|
-
function buildJournalContext(context, config) {
|
|
2043
|
-
const recentEntries = context.db.getRecentEntries(config.entryCount);
|
|
2043
|
+
function buildJournalContext(context, config, projectNumber) {
|
|
2044
|
+
const recentEntries = typeof projectNumber === "number" ? context.db.searchEntries("", { limit: config.entryCount, projectNumber }) : context.db.getRecentEntries(config.entryCount);
|
|
2044
2045
|
const latestEntries = recentEntries.map((e) => {
|
|
2045
2046
|
const content = e.content ?? "";
|
|
2046
2047
|
return {
|
|
@@ -2050,16 +2051,47 @@ function buildJournalContext(context, config) {
|
|
|
2050
2051
|
preview: content.slice(0, PREVIEW_LENGTH) + (content.length > PREVIEW_LENGTH ? "..." : "")
|
|
2051
2052
|
};
|
|
2052
2053
|
});
|
|
2054
|
+
const summaryEntries = typeof projectNumber === "number" ? context.db.searchEntries("", {
|
|
2055
|
+
limit: config.summaryCount,
|
|
2056
|
+
projectNumber,
|
|
2057
|
+
tags: ["session-summary"]
|
|
2058
|
+
}) : context.db.searchEntries("", {
|
|
2059
|
+
limit: config.summaryCount,
|
|
2060
|
+
tags: ["session-summary"]
|
|
2061
|
+
});
|
|
2062
|
+
const retroEntries = summaryEntries.length === 0 ? typeof projectNumber === "number" ? context.db.searchEntries("", {
|
|
2063
|
+
limit: config.summaryCount,
|
|
2064
|
+
projectNumber,
|
|
2065
|
+
entryType: "retrospective"
|
|
2066
|
+
}) : context.db.searchEntries("", {
|
|
2067
|
+
limit: config.summaryCount,
|
|
2068
|
+
entryType: "retrospective"
|
|
2069
|
+
}) : [];
|
|
2070
|
+
const finalSummaryEntries = summaryEntries.length > 0 ? summaryEntries : retroEntries;
|
|
2071
|
+
let latestSessionSummary;
|
|
2072
|
+
let sessionSummaries;
|
|
2073
|
+
if (finalSummaryEntries.length > 0) {
|
|
2074
|
+
sessionSummaries = finalSummaryEntries.map((entry) => {
|
|
2075
|
+
const c = entry.content ?? "";
|
|
2076
|
+
return {
|
|
2077
|
+
id: entry.id,
|
|
2078
|
+
timestamp: entry.timestamp,
|
|
2079
|
+
type: entry.entryType,
|
|
2080
|
+
preview: c.slice(0, PREVIEW_LENGTH) + (c.length > PREVIEW_LENGTH ? "..." : "")
|
|
2081
|
+
};
|
|
2082
|
+
});
|
|
2083
|
+
latestSessionSummary = sessionSummaries[0];
|
|
2084
|
+
}
|
|
2053
2085
|
const totalEntries = context.db.getActiveEntryCount();
|
|
2054
2086
|
const lastModified = recentEntries[0]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
2055
|
-
return { totalEntries, latestEntries, lastModified };
|
|
2087
|
+
return { totalEntries, latestEntries, latestSessionSummary, sessionSummaries, lastModified };
|
|
2056
2088
|
}
|
|
2057
2089
|
var TEAM_PREVIEW_LENGTH = 60;
|
|
2058
|
-
function buildTeamContext(context, config) {
|
|
2090
|
+
function buildTeamContext(context, config, projectNumber) {
|
|
2059
2091
|
if (!context.teamDb) return void 0;
|
|
2060
2092
|
try {
|
|
2061
2093
|
const teamTotalEntries = context.teamDb.getActiveEntryCount();
|
|
2062
|
-
const teamRecent = context.teamDb.getRecentEntries(1);
|
|
2094
|
+
const teamRecent = typeof projectNumber === "number" ? context.teamDb.searchEntries("", { limit: 1, projectNumber }) : context.teamDb.getRecentEntries(1);
|
|
2063
2095
|
const teamLatestEntry = teamRecent[0];
|
|
2064
2096
|
const teamContent = teamLatestEntry ? teamLatestEntry["content"] ?? "" : "";
|
|
2065
2097
|
const teamLatest = teamLatestEntry ? `#${String(teamLatestEntry["id"])}: ${teamContent.slice(0, TEAM_PREVIEW_LENGTH)}${teamContent.length > TEAM_PREVIEW_LENGTH ? "..." : ""}` : null;
|
|
@@ -2069,7 +2101,7 @@ function buildTeamContext(context, config) {
|
|
|
2069
2101
|
};
|
|
2070
2102
|
let teamLatestEntries = void 0;
|
|
2071
2103
|
if (config.includeTeam) {
|
|
2072
|
-
const teamEntries = context.teamDb.getRecentEntries(config.entryCount);
|
|
2104
|
+
const teamEntries = typeof projectNumber === "number" ? context.teamDb.searchEntries("", { limit: config.entryCount, projectNumber }) : context.teamDb.getRecentEntries(config.entryCount);
|
|
2073
2105
|
teamLatestEntries = teamEntries.map((e) => {
|
|
2074
2106
|
const content = e.content ?? "";
|
|
2075
2107
|
return {
|
|
@@ -2136,8 +2168,18 @@ function buildSkillsDirInfo(skillsDirPath) {
|
|
|
2136
2168
|
}
|
|
2137
2169
|
|
|
2138
2170
|
// src/handlers/resources/core/briefing/user-message.ts
|
|
2171
|
+
var escapeTableCell = (text) => text.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/\r?\n/g, "<br>");
|
|
2139
2172
|
function formatUserMessage(opts) {
|
|
2140
|
-
const {
|
|
2173
|
+
const {
|
|
2174
|
+
repoName,
|
|
2175
|
+
branchName,
|
|
2176
|
+
totalEntries,
|
|
2177
|
+
latestPreview,
|
|
2178
|
+
summaryPreviews,
|
|
2179
|
+
github,
|
|
2180
|
+
rulesFile,
|
|
2181
|
+
skillsDir
|
|
2182
|
+
} = opts;
|
|
2141
2183
|
let ciDisplay = opts.ciStatus;
|
|
2142
2184
|
if (github?.workflowSummary) {
|
|
2143
2185
|
const ws = github.workflowSummary;
|
|
@@ -2165,7 +2207,7 @@ function formatUserMessage(opts) {
|
|
|
2165
2207
|
if (github.openIssueList && github.openIssueList.length > 0) {
|
|
2166
2208
|
const titles = github.openIssueList.map((i) => `#${String(i.number)} ${i.title}`).join(" \xB7 ");
|
|
2167
2209
|
issuesRow = `
|
|
2168
|
-
| **Issues** | ${String(github.openIssues)} open: ${titles} |`;
|
|
2210
|
+
| **Issues** | ${String(github.openIssues)} open: ${escapeTableCell(titles)} |`;
|
|
2169
2211
|
} else {
|
|
2170
2212
|
issuesRow = `
|
|
2171
2213
|
| **Issues** | ${String(github.openIssues)} open |`;
|
|
@@ -2181,14 +2223,14 @@ function formatUserMessage(opts) {
|
|
|
2181
2223
|
} else if (github.openPrList && github.openPrList.length > 0) {
|
|
2182
2224
|
const titles = github.openPrList.map((p) => `#${String(p.number)} ${p.title}`).join(" \xB7 ");
|
|
2183
2225
|
prsRow = `
|
|
2184
|
-
| **PRs** | ${String(github.openPRs)} open: ${titles} |`;
|
|
2226
|
+
| **PRs** | ${String(github.openPRs)} open: ${escapeTableCell(titles)} |`;
|
|
2185
2227
|
} else {
|
|
2186
2228
|
prsRow = `
|
|
2187
2229
|
| **PRs** | ${String(github.openPRs)} open |`;
|
|
2188
2230
|
}
|
|
2189
2231
|
}
|
|
2190
2232
|
const milestoneRow = github?.milestones && github.milestones.length > 0 ? `
|
|
2191
|
-
| **Milestones** | ${github.milestones.map((m) => `${m.title} (${m.progress}${m.dueOn ? `, due ${m.dueOn.split("T")[0] ?? ""}` : ""})`).join(", ")} |` : "";
|
|
2233
|
+
| **Milestones** | ${escapeTableCell(github.milestones.map((m) => `${m.title} (${m.progress}${m.dueOn ? `, due ${m.dueOn.split("T")[0] ?? ""}` : ""})`).join(", "))} |` : "";
|
|
2192
2234
|
let insightsRow = "";
|
|
2193
2235
|
if (github?.insights) {
|
|
2194
2236
|
const parts = [];
|
|
@@ -2206,16 +2248,18 @@ function formatUserMessage(opts) {
|
|
|
2206
2248
|
}
|
|
2207
2249
|
const copilotRow = github?.copilotReviews ? `
|
|
2208
2250
|
| **Copilot** | ${String(github.copilotReviews.reviewed)} reviewed \xB7 ${String(github.copilotReviews.approved)} approved${github.copilotReviews.changesRequested > 0 ? ` \xB7 ${String(github.copilotReviews.changesRequested)} changes requested` : ""}${github.copilotReviews.totalComments > 0 ? ` (${String(github.copilotReviews.totalComments)} comments)` : ""} |` : "";
|
|
2251
|
+
const summariesOutput = summaryPreviews && summaryPreviews.length > 0 ? summaryPreviews.map((s) => `
|
|
2252
|
+
| **Summary** | ${escapeTableCell(s)} |`).join("") : "";
|
|
2209
2253
|
return `\u{1F4CB} **Session Context Loaded**
|
|
2210
2254
|
| Context | Value |
|
|
2211
2255
|
|---------|-------|
|
|
2212
|
-
| **Project** | ${repoName} |
|
|
2213
|
-
| **Branch** | ${branchName} |
|
|
2214
|
-
| **CI** | ${ciDisplay} |
|
|
2256
|
+
| **Project** | ${escapeTableCell(repoName)} |
|
|
2257
|
+
| **Branch** | ${escapeTableCell(branchName)} |
|
|
2258
|
+
| **CI** | ${escapeTableCell(ciDisplay)} |
|
|
2215
2259
|
| **Journal** | ${totalEntries} entries |${opts.teamTotalEntries !== void 0 ? `
|
|
2216
2260
|
| **Team DB** | ${opts.teamTotalEntries} entries |` : ""}
|
|
2217
|
-
| **Latest** | ${latestPreview} |${issuesRow}${prsRow}${milestoneRow}${insightsRow}${copilotRow}${rulesFile ? `
|
|
2218
|
-
| **Rules** | ${rulesFile.name} (${String(rulesFile.sizeKB)} KB, updated ${rulesFile.lastModified}) |` : ""}${skillsDir ? `
|
|
2261
|
+
| **Latest** | ${escapeTableCell(latestPreview)} |${summariesOutput}${issuesRow}${prsRow}${milestoneRow}${insightsRow}${copilotRow}${rulesFile ? `
|
|
2262
|
+
| **Rules** | ${escapeTableCell(rulesFile.name)} (${String(rulesFile.sizeKB)} KB, updated ${rulesFile.lastModified}) |` : ""}${skillsDir ? `
|
|
2219
2263
|
| **Skills** | ${String(skillsDir.count)} skill${skillsDir.count !== 1 ? "s" : ""} available |` : ""}`;
|
|
2220
2264
|
}
|
|
2221
2265
|
|
|
@@ -2252,24 +2296,28 @@ var dynamicBriefingResource = {
|
|
|
2252
2296
|
}
|
|
2253
2297
|
};
|
|
2254
2298
|
async function buildBriefingData(context, targetRepo) {
|
|
2255
|
-
const config = context.briefingConfig
|
|
2299
|
+
const config = { ...DEFAULT_BRIEFING_CONFIG, ...context.briefingConfig };
|
|
2256
2300
|
let activeGithub = context.github;
|
|
2301
|
+
let activeProjectNumber = config.defaultProjectNumber;
|
|
2257
2302
|
if (targetRepo && config.projectRegistry?.[targetRepo]) {
|
|
2258
2303
|
const repoPath = config.projectRegistry[targetRepo].path;
|
|
2259
2304
|
activeGithub = new GitHubIntegration(repoPath);
|
|
2305
|
+
activeProjectNumber = config.projectRegistry[targetRepo].project_number ?? void 0;
|
|
2260
2306
|
}
|
|
2261
|
-
const journal = buildJournalContext(context, config);
|
|
2307
|
+
const journal = buildJournalContext(context, config, activeProjectNumber);
|
|
2262
2308
|
const github = await buildGitHubSection(activeGithub, config);
|
|
2263
|
-
const team = buildTeamContext(context, config);
|
|
2309
|
+
const team = buildTeamContext(context, config, activeProjectNumber);
|
|
2264
2310
|
const rulesFile = buildRulesFileInfo(config.rulesFilePath);
|
|
2265
2311
|
const skillsDir = buildSkillsDirInfo(config.skillsDirPath);
|
|
2266
2312
|
const latestPreview = journal.latestEntries[0] ? `#${journal.latestEntries[0].id} (${journal.latestEntries[0].type}): ${journal.latestEntries[0].preview}` : "No entries yet";
|
|
2313
|
+
const summaryPreviews = journal.sessionSummaries ? journal.sessionSummaries.map((s) => `#${s.id} (${s.type}): ${s.preview}`) : null;
|
|
2267
2314
|
const userMessage = formatUserMessage({
|
|
2268
2315
|
repoName: github?.repo ?? "local",
|
|
2269
2316
|
branchName: github?.branch ?? "unknown",
|
|
2270
2317
|
ciStatus: github?.ci ?? "unknown",
|
|
2271
2318
|
totalEntries: journal.totalEntries,
|
|
2272
2319
|
latestPreview,
|
|
2320
|
+
summaryPreviews,
|
|
2273
2321
|
github,
|
|
2274
2322
|
teamTotalEntries: team?.teamInfo.totalEntries,
|
|
2275
2323
|
rulesFile,
|
|
@@ -2281,7 +2329,8 @@ async function buildBriefingData(context, targetRepo) {
|
|
|
2281
2329
|
serverTime: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2282
2330
|
journal: {
|
|
2283
2331
|
totalEntries: journal.totalEntries,
|
|
2284
|
-
latestEntries: journal.latestEntries
|
|
2332
|
+
latestEntries: journal.latestEntries,
|
|
2333
|
+
...journal.latestSessionSummary ? { latestSessionSummary: journal.latestSessionSummary } : {}
|
|
2285
2334
|
},
|
|
2286
2335
|
github,
|
|
2287
2336
|
teamContext: team?.teamInfo,
|
|
@@ -2324,7 +2373,7 @@ async function buildBriefingData(context, targetRepo) {
|
|
|
2324
2373
|
// src/constants/server-instructions.ts
|
|
2325
2374
|
var CORE_INSTRUCTIONS = `# memory-journal-mcp
|
|
2326
2375
|
|
|
2327
|
-
## ESSENTIAL SESSION START!**
|
|
2376
|
+
## **ESSENTIAL SESSION START!**
|
|
2328
2377
|
|
|
2329
2378
|
1. You **MUST** read the \`memory://briefing/{repo_name}\` at the start of each chat!
|
|
2330
2379
|
2. Use the standard MCP \`read_resource\` tool for this (do NOT use Code Mode/execute_code).
|
|
@@ -2384,6 +2433,13 @@ When you notice the user consistently applies patterns, preferences, or workflow
|
|
|
2384
2433
|
- **Always ask the user first** \u2014 never create or modify rules/skills silently
|
|
2385
2434
|
- Frame suggestions as: "I noticed you always [pattern]. Would you like me to add/update a rule for this?"
|
|
2386
2435
|
- For skills, explain the workflow it would automate and what triggers it
|
|
2436
|
+
|
|
2437
|
+
### Native Agent Skills (NPM Distribution)
|
|
2438
|
+
|
|
2439
|
+
This server leverages the \`neverinfamous-agent-skills\` package. If the user's \`SKILLS_DIR_PATH\` environment variable targets these, you have native access to foundational frameworks (\`mastering-typescript\`, \`react-best-practices\`, \`playwright-standard\`, \`golang\`, \`rust\`, \`shadcn-ui\`) and the \`github-commander\` DevOps workflows (\`issue-triage\`, \`pr-review\`, etc.).
|
|
2440
|
+
|
|
2441
|
+
- The user can distribute or update these skills across their repositories by running \`npx neverinfamous-agent-skills@latest\`.
|
|
2442
|
+
- If you need to create a new skill, reference the bundled \`skill-builder\` instructions!
|
|
2387
2443
|
`;
|
|
2388
2444
|
var COPILOT_REVIEW_INSTRUCTIONS = `
|
|
2389
2445
|
## Copilot Review Patterns
|
|
@@ -2420,65 +2476,18 @@ function buildQuickAccess(groups) {
|
|
|
2420
2476
|
return table;
|
|
2421
2477
|
}
|
|
2422
2478
|
var CODE_MODE_NAMESPACE_ROWS = [
|
|
2423
|
-
{
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
},
|
|
2429
|
-
{
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
namespace: "`mj.search.*`",
|
|
2433
|
-
example: '`mj.search.searchEntries("performance")`'
|
|
2434
|
-
},
|
|
2435
|
-
{
|
|
2436
|
-
group: "analytics",
|
|
2437
|
-
label: "Analytics",
|
|
2438
|
-
namespace: "`mj.analytics.*`",
|
|
2439
|
-
example: "`mj.analytics.getStatistics()`"
|
|
2440
|
-
},
|
|
2441
|
-
{
|
|
2442
|
-
group: "relationships",
|
|
2443
|
-
label: "Relationships",
|
|
2444
|
-
namespace: "`mj.relationships.*`",
|
|
2445
|
-
example: '`mj.relationships.linkEntries(1, 2, "implements")`'
|
|
2446
|
-
},
|
|
2447
|
-
{
|
|
2448
|
-
group: "io",
|
|
2449
|
-
label: "IO",
|
|
2450
|
-
namespace: "`mj.io.*`",
|
|
2451
|
-
example: '`mj.io.exportEntries("json")`'
|
|
2452
|
-
},
|
|
2453
|
-
{
|
|
2454
|
-
group: "admin",
|
|
2455
|
-
label: "Admin",
|
|
2456
|
-
namespace: "`mj.admin.*`",
|
|
2457
|
-
example: "`mj.admin.rebuildVectorIndex()`"
|
|
2458
|
-
},
|
|
2459
|
-
{
|
|
2460
|
-
group: "github",
|
|
2461
|
-
label: "GitHub",
|
|
2462
|
-
namespace: "`mj.github.*`",
|
|
2463
|
-
example: '`mj.github.getGithubIssues({ state: "open" })`'
|
|
2464
|
-
},
|
|
2465
|
-
{
|
|
2466
|
-
group: "backup",
|
|
2467
|
-
label: "Backup",
|
|
2468
|
-
namespace: "`mj.backup.*`",
|
|
2469
|
-
example: "`mj.backup.backupJournal()`"
|
|
2470
|
-
},
|
|
2471
|
-
{
|
|
2472
|
-
group: "team",
|
|
2473
|
-
label: "Team",
|
|
2474
|
-
namespace: "`mj.team.*`",
|
|
2475
|
-
example: '`mj.team.teamCreateEntry("Team update")`'
|
|
2476
|
-
}
|
|
2479
|
+
{ group: "core", label: "Core", namespace: "`mj.core.*`", example: '`mj.core.createEntry("Implemented feature X")`' },
|
|
2480
|
+
{ group: "search", label: "Search", namespace: "`mj.search.*`", example: '`mj.search.searchEntries("performance")`' },
|
|
2481
|
+
{ group: "analytics", label: "Analytics", namespace: "`mj.analytics.*`", example: "`mj.analytics.getStatistics()`" },
|
|
2482
|
+
{ group: "relationships", label: "Relationships", namespace: "`mj.relationships.*`", example: '`mj.relationships.linkEntries(1, 2, "implements")`' },
|
|
2483
|
+
{ group: "io", label: "IO", namespace: "`mj.io.*`", example: '`mj.io.exportEntries("json")`' },
|
|
2484
|
+
{ group: "admin", label: "Admin", namespace: "`mj.admin.*`", example: "`mj.admin.rebuildVectorIndex()`" },
|
|
2485
|
+
{ group: "github", label: "GitHub", namespace: "`mj.github.*`", example: '`mj.github.getGithubIssues({ state: "open" })`' },
|
|
2486
|
+
{ group: "backup", label: "Backup", namespace: "`mj.backup.*`", example: "`mj.backup.backupJournal()`" },
|
|
2487
|
+
{ group: "team", label: "Team", namespace: "`mj.team.*`", example: '`mj.team.teamCreateEntry("Team update")`' }
|
|
2477
2488
|
];
|
|
2478
2489
|
function buildCodeModeInstructions(groups) {
|
|
2479
|
-
const rows = CODE_MODE_NAMESPACE_ROWS.filter((r) => groups.has(r.group)).map(
|
|
2480
|
-
(r) => `| ${r.label.padEnd(13)} | ${r.namespace.padEnd(20)} | ${r.example.padEnd(50)} |`
|
|
2481
|
-
).join("\n");
|
|
2490
|
+
const rows = CODE_MODE_NAMESPACE_ROWS.filter((r) => groups.has(r.group)).map((r) => `| ${r.label.padEnd(13)} | ${r.namespace.padEnd(20)} | ${r.example.padEnd(50)} |`).join("\n");
|
|
2482
2491
|
const fullSection = CODE_MODE_FULL_TEXT;
|
|
2483
2492
|
const tableStart = fullSection.indexOf("| Group");
|
|
2484
2493
|
const tableEnd = fullSection.indexOf("\n\n**Features**");
|
|
@@ -2542,7 +2551,7 @@ var GITHUB_INSTRUCTIONS = `
|
|
|
2542
2551
|
- Include \`issue_number\`/\`pr_number\` in \`create_entry\` to auto-link
|
|
2543
2552
|
- After closing issue/merging PR \u2192 create summary entry with learnings
|
|
2544
2553
|
- CI failures \u2192 \`actions-failure-digest\` prompt or \`memory://actions/recent\`
|
|
2545
|
-
- Kanban: \`get_kanban_board\` \u2192 \`move_kanban_item\` \u2192 document completion (project_number auto-resolves if repo is registered)
|
|
2554
|
+
- Kanban: \`get_kanban_board\` \u2192 \`add_kanban_item\` / \`move_kanban_item\` / \`delete_kanban_item\` \u2192 document completion (project_number auto-resolves if repo is registered)
|
|
2546
2555
|
- Milestones: \`get_github_milestones\` \u2192 track project progress, \`memory://github/milestones\`
|
|
2547
2556
|
- **Multi-Project Routing**: If \`memory://briefing\` shows "Registered Workspaces":
|
|
2548
2557
|
- **Tools**: Pass a \`repo\` parameter to ALL GitHub tools (including \`get_github_context\`) to explicitly target a specific project.
|
|
@@ -2873,6 +2882,12 @@ Provide insights on patterns, productivity, and recommendations.`
|
|
|
2873
2882
|
LIMIT 20
|
|
2874
2883
|
`
|
|
2875
2884
|
);
|
|
2885
|
+
const mappedEntries = entries.map((e) => ({
|
|
2886
|
+
id: e["id"],
|
|
2887
|
+
type: e["entry_type"] ?? e["entryType"],
|
|
2888
|
+
timestamp: e["timestamp"],
|
|
2889
|
+
content: typeof e["content"] === "string" && e["content"].length > 250 ? e["content"].slice(0, 250) + "..." : e["content"]
|
|
2890
|
+
}));
|
|
2876
2891
|
return {
|
|
2877
2892
|
messages: [
|
|
2878
2893
|
{
|
|
@@ -2881,7 +2896,7 @@ Provide insights on patterns, productivity, and recommendations.`
|
|
|
2881
2896
|
type: "text",
|
|
2882
2897
|
text: `Track goals and milestones based on significant entries:
|
|
2883
2898
|
|
|
2884
|
-
${JSON.stringify(
|
|
2899
|
+
${JSON.stringify(mappedEntries, null, 2)}
|
|
2885
2900
|
|
|
2886
2901
|
Summarize progress toward goals and highlight achievements.`
|
|
2887
2902
|
}
|
|
@@ -3069,6 +3084,14 @@ ${entrySummary}
|
|
|
3069
3084
|
}
|
|
3070
3085
|
|
|
3071
3086
|
// src/handlers/prompts/github.ts
|
|
3087
|
+
function formatPromptEntries(entries, maxCount = 50) {
|
|
3088
|
+
return entries.slice(0, maxCount).map((e) => ({
|
|
3089
|
+
id: e["id"],
|
|
3090
|
+
type: e["entry_type"] ?? e["entryType"],
|
|
3091
|
+
timestamp: e["timestamp"],
|
|
3092
|
+
content: typeof e["content"] === "string" && e["content"].length > 250 ? e["content"].slice(0, 250) + "..." : e["content"]
|
|
3093
|
+
}));
|
|
3094
|
+
}
|
|
3072
3095
|
function getGitHubPromptDefinitions() {
|
|
3073
3096
|
return [
|
|
3074
3097
|
{
|
|
@@ -3099,7 +3122,7 @@ function getGitHubPromptDefinitions() {
|
|
|
3099
3122
|
type: "text",
|
|
3100
3123
|
text: `Generate a status summary for Project #${String(projectNumber)}:
|
|
3101
3124
|
|
|
3102
|
-
Entries: ${JSON.stringify(entries, null, 2)}
|
|
3125
|
+
Entries: ${JSON.stringify(formatPromptEntries(entries), null, 2)}
|
|
3103
3126
|
|
|
3104
3127
|
Provide: overview, recent activity, blockers, next steps.`
|
|
3105
3128
|
}
|
|
@@ -3133,7 +3156,7 @@ Provide: overview, recent activity, blockers, next steps.`
|
|
|
3133
3156
|
type: "text",
|
|
3134
3157
|
text: `Summarize PR #${String(prNumber)} activity:
|
|
3135
3158
|
|
|
3136
|
-
Journal entries: ${JSON.stringify(entries, null, 2)}
|
|
3159
|
+
Journal entries: ${JSON.stringify(formatPromptEntries(entries), null, 2)}
|
|
3137
3160
|
|
|
3138
3161
|
Provide: summary of changes, decisions made, testing done.`
|
|
3139
3162
|
}
|
|
@@ -3167,7 +3190,7 @@ Provide: summary of changes, decisions made, testing done.`
|
|
|
3167
3190
|
type: "text",
|
|
3168
3191
|
text: `Prepare for code review of PR #${String(prNumber)}:
|
|
3169
3192
|
|
|
3170
|
-
Context entries: ${JSON.stringify(entries, null, 2)}
|
|
3193
|
+
Context entries: ${JSON.stringify(formatPromptEntries(entries), null, 2)}
|
|
3171
3194
|
|
|
3172
3195
|
Provide: review checklist, areas of concern, testing recommendations.`
|
|
3173
3196
|
}
|
|
@@ -3201,7 +3224,7 @@ Provide: review checklist, areas of concern, testing recommendations.`
|
|
|
3201
3224
|
type: "text",
|
|
3202
3225
|
text: `Retrospective for PR #${String(prNumber)}:
|
|
3203
3226
|
|
|
3204
|
-
Journal entries: ${JSON.stringify(entries, null, 2)}
|
|
3227
|
+
Journal entries: ${JSON.stringify(formatPromptEntries(entries), null, 2)}
|
|
3205
3228
|
|
|
3206
3229
|
Provide: what went well, challenges, lessons learned.`
|
|
3207
3230
|
}
|
|
@@ -3234,7 +3257,7 @@ Provide: what went well, challenges, lessons learned.`
|
|
|
3234
3257
|
type: "text",
|
|
3235
3258
|
text: `Analyze CI/CD failures from these workflow entries:
|
|
3236
3259
|
|
|
3237
|
-
${JSON.stringify(entries, null, 2)}
|
|
3260
|
+
${JSON.stringify(formatPromptEntries(entries), null, 2)}
|
|
3238
3261
|
|
|
3239
3262
|
Provide: failure patterns, root causes, remediation steps.`
|
|
3240
3263
|
}
|
|
@@ -3271,7 +3294,7 @@ Provide: failure patterns, root causes, remediation steps.`
|
|
|
3271
3294
|
type: "text",
|
|
3272
3295
|
text: `Track milestones for Project #${String(projectNumber)}:
|
|
3273
3296
|
|
|
3274
|
-
Milestone entries: ${JSON.stringify(entries, null, 2)}
|
|
3297
|
+
Milestone entries: ${JSON.stringify(formatPromptEntries(entries), null, 2)}
|
|
3275
3298
|
|
|
3276
3299
|
Provide: progress summary, upcoming milestones, timeline.`
|
|
3277
3300
|
}
|
|
@@ -3528,6 +3551,9 @@ var statisticsResource = {
|
|
|
3528
3551
|
return context.db.getStatistics("week");
|
|
3529
3552
|
}
|
|
3530
3553
|
};
|
|
3554
|
+
var cachedRulesContent = null;
|
|
3555
|
+
var rulesLastScanTime = 0;
|
|
3556
|
+
var RULES_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
3531
3557
|
var rulesResource = {
|
|
3532
3558
|
uri: "memory://rules",
|
|
3533
3559
|
name: "Rules File",
|
|
@@ -3536,7 +3562,7 @@ var rulesResource = {
|
|
|
3536
3562
|
mimeType: "text/markdown",
|
|
3537
3563
|
icons: [ICON_BRIEFING],
|
|
3538
3564
|
annotations: withPriority(0.7, ASSISTANT_FOCUSED),
|
|
3539
|
-
handler: (_uri, _context) => {
|
|
3565
|
+
handler: async (_uri, _context) => {
|
|
3540
3566
|
const rulesPath = process.env["RULES_FILE_PATH"];
|
|
3541
3567
|
if (!rulesPath) {
|
|
3542
3568
|
return {
|
|
@@ -3547,11 +3573,24 @@ var rulesResource = {
|
|
|
3547
3573
|
};
|
|
3548
3574
|
}
|
|
3549
3575
|
try {
|
|
3550
|
-
|
|
3576
|
+
if (cachedRulesContent && Date.now() - rulesLastScanTime < RULES_CACHE_TTL_MS) {
|
|
3577
|
+
const stat2 = await fs2.promises.stat(rulesPath).catch(() => ({ mtimeMs: Date.now() }));
|
|
3578
|
+
return {
|
|
3579
|
+
data: cachedRulesContent,
|
|
3580
|
+
annotations: {
|
|
3581
|
+
lastModified: new Date(stat2.mtimeMs).toISOString()
|
|
3582
|
+
}
|
|
3583
|
+
};
|
|
3584
|
+
}
|
|
3585
|
+
const content = await fs2.promises.readFile(rulesPath, "utf8");
|
|
3586
|
+
const stat = await fs2.promises.stat(rulesPath).catch(() => ({ mtimeMs: Date.now() }));
|
|
3587
|
+
const mtimeMs = stat.mtimeMs;
|
|
3588
|
+
cachedRulesContent = content;
|
|
3589
|
+
rulesLastScanTime = Date.now();
|
|
3551
3590
|
return {
|
|
3552
3591
|
data: content,
|
|
3553
3592
|
annotations: {
|
|
3554
|
-
lastModified: new Date(
|
|
3593
|
+
lastModified: new Date(mtimeMs).toISOString()
|
|
3555
3594
|
}
|
|
3556
3595
|
};
|
|
3557
3596
|
} catch (err) {
|
|
@@ -3617,15 +3656,15 @@ function getShippedSkillsDir() {
|
|
|
3617
3656
|
return void 0;
|
|
3618
3657
|
}
|
|
3619
3658
|
}
|
|
3620
|
-
function scanSkillsDir(dir, source) {
|
|
3659
|
+
async function scanSkillsDir(dir, source) {
|
|
3621
3660
|
if (!fs2.existsSync(dir)) return [];
|
|
3622
|
-
const entries = fs2.
|
|
3661
|
+
const entries = await fs2.promises.readdir(dir, { withFileTypes: true });
|
|
3623
3662
|
const skills = [];
|
|
3624
3663
|
for (const entry of entries) {
|
|
3625
3664
|
if (!entry.isDirectory()) continue;
|
|
3626
3665
|
const skillMdPath = path4.join(dir, entry.name, "SKILL.md");
|
|
3627
3666
|
if (!fs2.existsSync(skillMdPath)) continue;
|
|
3628
|
-
const content = fs2.
|
|
3667
|
+
const content = await fs2.promises.readFile(skillMdPath, "utf8");
|
|
3629
3668
|
const lines = content.split("\n");
|
|
3630
3669
|
const excerptLine = lines.find(
|
|
3631
3670
|
(l) => l.trim().length > 0 && !l.startsWith("#") && !l.startsWith("---")
|
|
@@ -3643,7 +3682,7 @@ var skillsResource = {
|
|
|
3643
3682
|
mimeType: "application/json",
|
|
3644
3683
|
icons: [ICON_BRIEFING],
|
|
3645
3684
|
annotations: { ...MEDIUM_PRIORITY, audience: ["assistant"] },
|
|
3646
|
-
handler: (_uri, _context) => {
|
|
3685
|
+
handler: async (_uri, _context) => {
|
|
3647
3686
|
const userSkillsDir = process.env["SKILLS_DIR_PATH"];
|
|
3648
3687
|
const shippedSkillsDir = getShippedSkillsDir();
|
|
3649
3688
|
const hasAnySource = !!userSkillsDir || !!shippedSkillsDir;
|
|
@@ -3670,12 +3709,12 @@ var skillsResource = {
|
|
|
3670
3709
|
}
|
|
3671
3710
|
const skillMap = /* @__PURE__ */ new Map();
|
|
3672
3711
|
if (shippedSkillsDir) {
|
|
3673
|
-
for (const skill of scanSkillsDir(shippedSkillsDir, "shipped")) {
|
|
3712
|
+
for (const skill of await scanSkillsDir(shippedSkillsDir, "shipped")) {
|
|
3674
3713
|
skillMap.set(skill.name, skill);
|
|
3675
3714
|
}
|
|
3676
3715
|
}
|
|
3677
3716
|
if (userSkillsDir) {
|
|
3678
|
-
for (const skill of scanSkillsDir(userSkillsDir, "user")) {
|
|
3717
|
+
for (const skill of await scanSkillsDir(userSkillsDir, "user")) {
|
|
3679
3718
|
skillMap.set(skill.name, skill);
|
|
3680
3719
|
}
|
|
3681
3720
|
}
|
|
@@ -4894,7 +4933,7 @@ function getHelpResourceDefinitions() {
|
|
|
4894
4933
|
var toolIndexModule = null;
|
|
4895
4934
|
async function getAllToolDefinitionsAsync(context) {
|
|
4896
4935
|
try {
|
|
4897
|
-
toolIndexModule ??= await import('./tools-
|
|
4936
|
+
toolIndexModule ??= await import('./tools-CXR2FEB2.js');
|
|
4898
4937
|
if (toolIndexModule === null) return [];
|
|
4899
4938
|
const tools = toolIndexModule.getTools(context.db, null);
|
|
4900
4939
|
return tools.map((t) => ({
|
|
@@ -496,6 +496,40 @@ var IssuesManager = class {
|
|
|
496
496
|
return null;
|
|
497
497
|
}
|
|
498
498
|
}
|
|
499
|
+
async getIssueComments(owner, repo, issueNumber, limit = 30) {
|
|
500
|
+
const _limit = Math.min(limit, 100);
|
|
501
|
+
if (_limit <= 0) return [];
|
|
502
|
+
if (!this.client.octokit) {
|
|
503
|
+
return [];
|
|
504
|
+
}
|
|
505
|
+
const cacheKey = `issue-comments:${owner}:${repo}:${String(issueNumber)}:${String(_limit)}`;
|
|
506
|
+
const cached = this.client.getCached(cacheKey);
|
|
507
|
+
if (cached) return cached;
|
|
508
|
+
try {
|
|
509
|
+
const response = await this.client.octokit.issues.listComments({
|
|
510
|
+
owner,
|
|
511
|
+
repo,
|
|
512
|
+
issue_number: issueNumber,
|
|
513
|
+
per_page: _limit,
|
|
514
|
+
sort: "created",
|
|
515
|
+
direction: "asc"
|
|
516
|
+
});
|
|
517
|
+
const comments = response.data.slice(0, _limit).map((comment) => ({
|
|
518
|
+
author: comment.user?.login ?? "unknown",
|
|
519
|
+
body: comment.body ?? "",
|
|
520
|
+
createdAt: comment.created_at
|
|
521
|
+
}));
|
|
522
|
+
this.client.setCache(cacheKey, comments);
|
|
523
|
+
return comments;
|
|
524
|
+
} catch (error) {
|
|
525
|
+
logger.error("Failed to get issue comments", {
|
|
526
|
+
module: "GitHub",
|
|
527
|
+
entityId: issueNumber,
|
|
528
|
+
error: error instanceof Error ? error.message : String(error)
|
|
529
|
+
});
|
|
530
|
+
return [];
|
|
531
|
+
}
|
|
532
|
+
}
|
|
499
533
|
async createIssue(owner, repo, title, body, labels, assignees, milestone) {
|
|
500
534
|
if (!this.client.octokit) {
|
|
501
535
|
logger.error("Cannot create issue: GitHub API not available", { module: "GitHub" });
|
|
@@ -1034,7 +1068,9 @@ var ProjectsManager = class {
|
|
|
1034
1068
|
});
|
|
1035
1069
|
return { success: false, error: errorMessage };
|
|
1036
1070
|
} finally {
|
|
1037
|
-
this.client.invalidateCache
|
|
1071
|
+
if (typeof this.client.invalidateCache === "function") {
|
|
1072
|
+
this.client.invalidateCache("kanban:");
|
|
1073
|
+
}
|
|
1038
1074
|
}
|
|
1039
1075
|
}
|
|
1040
1076
|
async addProjectItem(projectId, contentId) {
|
|
@@ -1070,7 +1106,44 @@ var ProjectsManager = class {
|
|
|
1070
1106
|
});
|
|
1071
1107
|
return { success: false, error: errorMessage };
|
|
1072
1108
|
} finally {
|
|
1073
|
-
this.client.invalidateCache
|
|
1109
|
+
if (typeof this.client.invalidateCache === "function") {
|
|
1110
|
+
this.client.invalidateCache("kanban:");
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
async deleteProjectItem(projectId, itemId) {
|
|
1115
|
+
if (!this.client.graphqlWithAuth) {
|
|
1116
|
+
return { success: false, error: "GraphQL not available - no token" };
|
|
1117
|
+
}
|
|
1118
|
+
try {
|
|
1119
|
+
const mutation = `
|
|
1120
|
+
mutation($projectId: ID!, $itemId: ID!) {
|
|
1121
|
+
deleteProjectV2Item(input: { projectId: $projectId, itemId: $itemId }) {
|
|
1122
|
+
deletedItemId
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
`;
|
|
1126
|
+
await this.client.graphqlWithAuth(mutation, {
|
|
1127
|
+
projectId,
|
|
1128
|
+
itemId
|
|
1129
|
+
});
|
|
1130
|
+
logger.info("Deleted project item", {
|
|
1131
|
+
module: "GitHub",
|
|
1132
|
+
context: { projectId, itemId }
|
|
1133
|
+
});
|
|
1134
|
+
return { success: true };
|
|
1135
|
+
} catch (error) {
|
|
1136
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1137
|
+
logger.error("Failed to delete item from project", {
|
|
1138
|
+
module: "GitHub",
|
|
1139
|
+
context: { projectId, itemId },
|
|
1140
|
+
error: errorMessage
|
|
1141
|
+
});
|
|
1142
|
+
return { success: false, error: errorMessage };
|
|
1143
|
+
} finally {
|
|
1144
|
+
if (typeof this.client.invalidateCache === "function") {
|
|
1145
|
+
this.client.invalidateCache("kanban:");
|
|
1146
|
+
}
|
|
1074
1147
|
}
|
|
1075
1148
|
}
|
|
1076
1149
|
};
|
|
@@ -1540,6 +1613,9 @@ var GitHubIntegration = class {
|
|
|
1540
1613
|
async getIssue(owner, repo, issueNumber) {
|
|
1541
1614
|
return this.issuesManager.getIssue(owner, repo, issueNumber);
|
|
1542
1615
|
}
|
|
1616
|
+
async getIssueComments(owner, repo, issueNumber, limit = 30) {
|
|
1617
|
+
return this.issuesManager.getIssueComments(owner, repo, issueNumber, limit);
|
|
1618
|
+
}
|
|
1543
1619
|
async createIssue(owner, repo, title, body, labels, assignees, milestone) {
|
|
1544
1620
|
return this.issuesManager.createIssue(
|
|
1545
1621
|
owner,
|
|
@@ -1634,6 +1710,9 @@ var GitHubIntegration = class {
|
|
|
1634
1710
|
async addProjectItem(projectId, contentId) {
|
|
1635
1711
|
return this.projectsManager.addProjectItem(projectId, contentId);
|
|
1636
1712
|
}
|
|
1713
|
+
async deleteProjectItem(projectId, itemId) {
|
|
1714
|
+
return this.projectsManager.deleteProjectItem(projectId, itemId);
|
|
1715
|
+
}
|
|
1637
1716
|
async getMilestones(owner, repo, state = "open", limit = 20) {
|
|
1638
1717
|
return this.milestonesManager.getMilestones(owner, repo, state, limit);
|
|
1639
1718
|
}
|