memory-journal-mcp 7.1.0 → 7.3.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-CHWIPVQN.js} +174 -74
- package/dist/{chunk-37BQOJDZ.js → chunk-WXDEVIFL.js} +87 -8
- package/dist/{chunk-JEGRDY6W.js → chunk-ZJJD2F5T.js} +487 -89
- package/dist/cli.js +30 -4
- package/dist/github-integration-YODGZH3K.js +1 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -3
- package/dist/{tools-O44Q52RD.js → tools-MNMGDTQI.js} +2 -2
- package/package.json +4 -4
- 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
1
|
import { transformAutoReturn } from './chunk-OKOVZ5QE.js';
|
|
2
|
-
import { GitHubIntegration, resolveAuthor, logger, assertSafeDirectoryPath, MemoryJournalMcpError, matchSuggestion, ConfigurationError } from './chunk-
|
|
2
|
+
import { GitHubIntegration, resolveAuthor, logger, ValidationError, ResourceNotFoundError, assertSafeDirectoryPath, MemoryJournalMcpError, matchSuggestion, ConfigurationError } from './chunk-WXDEVIFL.js';
|
|
3
3
|
import { z, ZodError } from 'zod';
|
|
4
4
|
import { open, stat, mkdir, rename, appendFile, readdir, readFile } from 'fs/promises';
|
|
5
5
|
import { tmpdir } from 'os';
|
|
@@ -59,7 +59,7 @@ async function resolveIssueUrl(context, projectNumber, issueNumber, existingUrl)
|
|
|
59
59
|
([_, v]) => v.project_number === projectNumber
|
|
60
60
|
);
|
|
61
61
|
if (entry) {
|
|
62
|
-
const { GitHubIntegration: GitHubIntegration2 } = await import('./github-integration-
|
|
62
|
+
const { GitHubIntegration: GitHubIntegration2 } = await import('./github-integration-YODGZH3K.js');
|
|
63
63
|
const targetGithub = new GitHubIntegration2(entry[1].path);
|
|
64
64
|
const repoInfo = await targetGithub.getRepoInfo();
|
|
65
65
|
if (repoInfo.owner && repoInfo.repo) {
|
|
@@ -114,6 +114,7 @@ var SIGNIFICANCE_TYPES = [
|
|
|
114
114
|
"release"
|
|
115
115
|
];
|
|
116
116
|
var MAX_CONTENT_LENGTH = 5e4;
|
|
117
|
+
var MAX_QUERY_LIMIT = 500;
|
|
117
118
|
var DATE_MIN_SENTINEL = "1970-01-01";
|
|
118
119
|
var DATE_MAX_SENTINEL = "2999-12-31";
|
|
119
120
|
var DATE_FORMAT_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
@@ -207,7 +208,7 @@ var CreateEntrySchemaMcp = z.object({
|
|
|
207
208
|
share_with_team: z.boolean().optional().default(false)
|
|
208
209
|
});
|
|
209
210
|
var GetEntryByIdSchema = z.object({
|
|
210
|
-
entry_id: z.number(),
|
|
211
|
+
entry_id: z.number().int(),
|
|
211
212
|
include_relationships: z.boolean().optional().default(true)
|
|
212
213
|
});
|
|
213
214
|
var GetEntryByIdSchemaMcp = z.object({
|
|
@@ -215,7 +216,7 @@ var GetEntryByIdSchemaMcp = z.object({
|
|
|
215
216
|
include_relationships: z.boolean().optional().default(true)
|
|
216
217
|
});
|
|
217
218
|
var GetRecentEntriesSchema = z.object({
|
|
218
|
-
limit: z.number().max(
|
|
219
|
+
limit: z.number().min(1).max(MAX_QUERY_LIMIT).optional().default(5),
|
|
219
220
|
is_personal: z.boolean().optional()
|
|
220
221
|
});
|
|
221
222
|
var GetRecentEntriesSchemaMcp = z.object({
|
|
@@ -246,6 +247,7 @@ var EntryByIdOutputSchema = z.object({
|
|
|
246
247
|
error: z.string().optional()
|
|
247
248
|
}).extend(ErrorFieldsMixin.shape);
|
|
248
249
|
var TestSimpleOutputSchema = z.object({
|
|
250
|
+
success: z.boolean().optional(),
|
|
249
251
|
message: z.string()
|
|
250
252
|
}).extend(ErrorFieldsMixin.shape);
|
|
251
253
|
var TagsListOutputSchema = z.object({
|
|
@@ -363,6 +365,7 @@ function getCoreTools(context) {
|
|
|
363
365
|
}
|
|
364
366
|
const { score: importance, breakdown: importanceBreakdown } = db.calculateImportance(entry_id);
|
|
365
367
|
const result = {
|
|
368
|
+
success: true,
|
|
366
369
|
entry,
|
|
367
370
|
importance,
|
|
368
371
|
importanceBreakdown
|
|
@@ -388,7 +391,7 @@ function getCoreTools(context) {
|
|
|
388
391
|
try {
|
|
389
392
|
const { limit, is_personal } = GetRecentEntriesSchema.parse(params);
|
|
390
393
|
const entries = db.getRecentEntries(limit, is_personal);
|
|
391
|
-
return { entries, count: entries.length };
|
|
394
|
+
return { success: true, entries, count: entries.length };
|
|
392
395
|
} catch (err) {
|
|
393
396
|
return formatHandlerError(err);
|
|
394
397
|
}
|
|
@@ -424,7 +427,7 @@ function getCoreTools(context) {
|
|
|
424
427
|
handler: (params) => {
|
|
425
428
|
try {
|
|
426
429
|
const { message } = TestSimpleSchema.parse(params);
|
|
427
|
-
return { message: `Test response: ${message}` };
|
|
430
|
+
return { success: true, message: `Test response: ${message}` };
|
|
428
431
|
} catch (err) {
|
|
429
432
|
return formatHandlerError(err);
|
|
430
433
|
}
|
|
@@ -442,7 +445,7 @@ function getCoreTools(context) {
|
|
|
442
445
|
try {
|
|
443
446
|
const rawTags = db.listTags();
|
|
444
447
|
const tags = rawTags.map((t) => ({ name: t.name, count: t.usageCount }));
|
|
445
|
-
return { tags, count: tags.length };
|
|
448
|
+
return { success: true, tags, count: tags.length };
|
|
446
449
|
} catch (err) {
|
|
447
450
|
return formatHandlerError(err);
|
|
448
451
|
}
|
|
@@ -452,7 +455,6 @@ function getCoreTools(context) {
|
|
|
452
455
|
}
|
|
453
456
|
|
|
454
457
|
// src/handlers/tools/search/helpers.ts
|
|
455
|
-
var MAX_QUERY_LIMIT = 500;
|
|
456
458
|
var DEDUP_KEY_LENGTH = 200;
|
|
457
459
|
function calcPerDbLimit(limit, hasTeamDb) {
|
|
458
460
|
return hasTeamDb ? Math.min(limit * 2, MAX_QUERY_LIMIT) : limit;
|
|
@@ -470,6 +472,30 @@ function mergeAndDedup(personal, team, limit) {
|
|
|
470
472
|
}
|
|
471
473
|
return limit !== void 0 ? merged.slice(0, limit) : merged;
|
|
472
474
|
}
|
|
475
|
+
function passMetadataFilters(entry, options, db) {
|
|
476
|
+
if (options.isPersonal !== void 0 && entry.isPersonal !== options.isPersonal) return false;
|
|
477
|
+
if (options.projectNumber !== void 0 && entry.projectNumber !== options.projectNumber)
|
|
478
|
+
return false;
|
|
479
|
+
if (options.issueNumber !== void 0 && entry.issueNumber !== options.issueNumber) return false;
|
|
480
|
+
if (options.prNumber !== void 0 && entry.prNumber !== options.prNumber) return false;
|
|
481
|
+
if (options.prStatus !== void 0 && entry.prStatus !== options.prStatus) return false;
|
|
482
|
+
if (options.workflowRunId !== void 0 && entry.workflowRunId !== options.workflowRunId)
|
|
483
|
+
return false;
|
|
484
|
+
if (options.entryType && entry.entryType !== options.entryType) return false;
|
|
485
|
+
if (options.startDate) {
|
|
486
|
+
const entryDate = entry.timestamp.split("T")[0] ?? "";
|
|
487
|
+
if (entryDate < options.startDate) return false;
|
|
488
|
+
}
|
|
489
|
+
if (options.endDate) {
|
|
490
|
+
const entryDate = entry.timestamp.split("T")[0] ?? "";
|
|
491
|
+
if (entryDate > options.endDate) return false;
|
|
492
|
+
}
|
|
493
|
+
if (options.tags && options.tags.length > 0) {
|
|
494
|
+
const entryTags = Array.isArray(entry.tags) ? entry.tags : db.getTagsForEntry(entry.id);
|
|
495
|
+
if (!options.tags.some((t) => entryTags.includes(t))) return false;
|
|
496
|
+
}
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
473
499
|
|
|
474
500
|
// src/handlers/tools/search/auto.ts
|
|
475
501
|
var QUESTION_PATTERNS = [
|
|
@@ -603,7 +629,7 @@ async function hybridSearch(query, db, vectorManager, options) {
|
|
|
603
629
|
for (const id of sortedIds) {
|
|
604
630
|
const entry = entriesMap.get(id);
|
|
605
631
|
if (!entry) continue;
|
|
606
|
-
if (
|
|
632
|
+
if (!passMetadataFilters(entry, options, db)) continue;
|
|
607
633
|
entries.push({ ...entry, source: "personal" });
|
|
608
634
|
}
|
|
609
635
|
return { entries, fusionScores };
|
|
@@ -730,11 +756,25 @@ function getSearchTools(context) {
|
|
|
730
756
|
handler: async (params) => {
|
|
731
757
|
try {
|
|
732
758
|
const input = SearchEntriesSchema.parse(params);
|
|
733
|
-
const query = input.query || "";
|
|
759
|
+
const query = input.query?.trim() || "";
|
|
734
760
|
const mode = input.mode;
|
|
735
|
-
const { resolvedMode, isAuto } = resolveSearchMode(mode, query);
|
|
736
761
|
const hasFilters = input.project_number !== void 0 || input.issue_number !== void 0 || input.pr_number !== void 0 || input.pr_status !== void 0 || input.workflow_run_id !== void 0 || input.is_personal !== void 0 || input.tags !== void 0 || input.entry_type !== void 0 || input.start_date !== void 0 || input.end_date !== void 0;
|
|
737
|
-
|
|
762
|
+
if (!query && !hasFilters) {
|
|
763
|
+
return {
|
|
764
|
+
...formatHandlerError(
|
|
765
|
+
new ValidationError(
|
|
766
|
+
"Search requires either a query string or at least one filter",
|
|
767
|
+
{
|
|
768
|
+
suggestion: "Provide a search query or use get_recent_entries instead"
|
|
769
|
+
}
|
|
770
|
+
)
|
|
771
|
+
),
|
|
772
|
+
entries: [],
|
|
773
|
+
count: 0
|
|
774
|
+
};
|
|
775
|
+
}
|
|
776
|
+
const { resolvedMode, isAuto } = resolveSearchMode(mode, query);
|
|
777
|
+
const effectiveMode = resolvedMode;
|
|
738
778
|
const searchOptions = {
|
|
739
779
|
limit: input.limit,
|
|
740
780
|
isPersonal: input.is_personal,
|
|
@@ -754,9 +794,10 @@ function getSearchTools(context) {
|
|
|
754
794
|
const result = ftsSearch(input.query, db, teamDb, searchOptions);
|
|
755
795
|
return { ...result, searchMode: "fts (fallback)" };
|
|
756
796
|
}
|
|
797
|
+
const internalLimit = hasFilters ? Math.min(Math.max(input.limit * 10, 100), 1e3) : input.limit * 2;
|
|
757
798
|
const semanticResults = await vectorManager.search(
|
|
758
799
|
query,
|
|
759
|
-
|
|
800
|
+
internalLimit,
|
|
760
801
|
0.25
|
|
761
802
|
);
|
|
762
803
|
const entryIds = semanticResults.map((r) => r.entryId);
|
|
@@ -764,11 +805,11 @@ function getSearchTools(context) {
|
|
|
764
805
|
const entries = semanticResults.map((r) => {
|
|
765
806
|
const entry = entriesMap.get(r.entryId);
|
|
766
807
|
if (!entry) return null;
|
|
767
|
-
if (
|
|
768
|
-
return null;
|
|
808
|
+
if (!passMetadataFilters(entry, searchOptions, db)) return null;
|
|
769
809
|
return { ...entry, source: "personal" };
|
|
770
810
|
}).filter((e) => e !== null);
|
|
771
811
|
return {
|
|
812
|
+
success: true,
|
|
772
813
|
entries,
|
|
773
814
|
count: entries.length,
|
|
774
815
|
searchMode: isAuto ? "semantic (auto)" : "semantic"
|
|
@@ -786,6 +827,7 @@ function getSearchTools(context) {
|
|
|
786
827
|
searchOptions
|
|
787
828
|
);
|
|
788
829
|
return {
|
|
830
|
+
success: true,
|
|
789
831
|
entries,
|
|
790
832
|
count: entries.length,
|
|
791
833
|
searchMode: isAuto ? "hybrid (auto)" : "hybrid"
|
|
@@ -796,6 +838,7 @@ function getSearchTools(context) {
|
|
|
796
838
|
const result = ftsSearch(input.query, db, teamDb, searchOptions);
|
|
797
839
|
return {
|
|
798
840
|
...result,
|
|
841
|
+
success: true,
|
|
799
842
|
searchMode: isAuto ? "fts (auto)" : "fts"
|
|
800
843
|
};
|
|
801
844
|
}
|
|
@@ -856,9 +899,13 @@ function getSearchTools(context) {
|
|
|
856
899
|
teamEntries.map((e) => ({ ...e, source: "team" })),
|
|
857
900
|
input.limit
|
|
858
901
|
);
|
|
859
|
-
return { entries: merged, count: merged.length };
|
|
902
|
+
return { success: true, entries: merged, count: merged.length };
|
|
860
903
|
}
|
|
861
|
-
return {
|
|
904
|
+
return {
|
|
905
|
+
success: true,
|
|
906
|
+
entries: personalEntries,
|
|
907
|
+
count: personalEntries.length
|
|
908
|
+
};
|
|
862
909
|
} catch (err) {
|
|
863
910
|
return formatHandlerError(err);
|
|
864
911
|
}
|
|
@@ -900,17 +947,19 @@ function getSearchTools(context) {
|
|
|
900
947
|
count: 0
|
|
901
948
|
};
|
|
902
949
|
}
|
|
950
|
+
const hasFilters = input.is_personal !== void 0 || input.tags !== void 0 || input.entry_type !== void 0 || input.start_date !== void 0 || input.end_date !== void 0;
|
|
951
|
+
const internalLimit = hasFilters ? Math.min(Math.max(input.limit * 10, 100), 1e3) : input.limit * 2;
|
|
903
952
|
let results;
|
|
904
953
|
if (input.entry_id !== void 0) {
|
|
905
954
|
results = await vectorManager.searchByEntryId(
|
|
906
955
|
input.entry_id,
|
|
907
|
-
|
|
956
|
+
internalLimit,
|
|
908
957
|
input.similarity_threshold ?? 0.25
|
|
909
958
|
);
|
|
910
959
|
} else {
|
|
911
960
|
results = await vectorManager.search(
|
|
912
961
|
input.query ?? "",
|
|
913
|
-
|
|
962
|
+
internalLimit,
|
|
914
963
|
input.similarity_threshold ?? 0.25
|
|
915
964
|
);
|
|
916
965
|
}
|
|
@@ -919,29 +968,21 @@ function getSearchTools(context) {
|
|
|
919
968
|
const entries = results.map((r) => {
|
|
920
969
|
const entry = entriesMap.get(r.entryId);
|
|
921
970
|
if (!entry) return null;
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
if (input.start_date) {
|
|
931
|
-
const entryDate = entry.timestamp.split("T")[0] ?? "";
|
|
932
|
-
if (entryDate < input.start_date) return null;
|
|
933
|
-
}
|
|
934
|
-
if (input.end_date) {
|
|
935
|
-
const entryDate = entry.timestamp.split("T")[0] ?? "";
|
|
936
|
-
if (entryDate > input.end_date) return null;
|
|
937
|
-
}
|
|
971
|
+
const filterOptions = {
|
|
972
|
+
isPersonal: input.is_personal,
|
|
973
|
+
tags: input.tags,
|
|
974
|
+
entryType: input.entry_type,
|
|
975
|
+
startDate: input.start_date,
|
|
976
|
+
endDate: input.end_date
|
|
977
|
+
};
|
|
978
|
+
if (!passMetadataFilters(entry, filterOptions, db)) return null;
|
|
938
979
|
if (input.entry_id !== void 0 && entry.id === input.entry_id)
|
|
939
980
|
return null;
|
|
940
981
|
return {
|
|
941
982
|
...entry,
|
|
942
983
|
similarity: Math.round(r.score * 100) / 100
|
|
943
984
|
};
|
|
944
|
-
}).filter((e) => e !== null);
|
|
985
|
+
}).filter((e) => e !== null).slice(0, input.limit);
|
|
945
986
|
const stats = vectorManager.getStats();
|
|
946
987
|
const isIndexEmpty = stats.itemCount === 0;
|
|
947
988
|
const includeHint = input.hint_on_empty ?? true;
|
|
@@ -950,6 +991,7 @@ function getSearchTools(context) {
|
|
|
950
991
|
const allNoise = entries.length > 0 && bestSimilarity < QUALITY_FLOOR2;
|
|
951
992
|
const hint = isIndexEmpty && includeHint ? "No entries in vector index. Use rebuild_vector_index to index existing entries." : entries.length === 0 && includeHint ? `No entries matched your query above the similarity threshold (${String(input.similarity_threshold ?? 0.25)}). Try lowering similarity_threshold (e.g., 0.15) for broader matches.` : allNoise ? `Results may be noise \u2014 best similarity (${String(bestSimilarity)}) is below quality floor (${String(QUALITY_FLOOR2)}). Try a more specific query or raise similarity_threshold to filter weak matches.` : void 0;
|
|
952
993
|
return {
|
|
994
|
+
success: true,
|
|
953
995
|
query: input.query,
|
|
954
996
|
...input.entry_id !== void 0 ? { entryId: input.entry_id } : {},
|
|
955
997
|
entries,
|
|
@@ -1108,7 +1150,7 @@ function getAnalyticsTools(context) {
|
|
|
1108
1150
|
end_date,
|
|
1109
1151
|
project_breakdown
|
|
1110
1152
|
);
|
|
1111
|
-
return { ...stats, groupBy: group_by };
|
|
1153
|
+
return { success: true, ...stats, groupBy: group_by };
|
|
1112
1154
|
} catch (err) {
|
|
1113
1155
|
return formatHandlerError(err);
|
|
1114
1156
|
}
|
|
@@ -1150,6 +1192,7 @@ function getAnalyticsTools(context) {
|
|
|
1150
1192
|
);
|
|
1151
1193
|
if (!projectsResult[0] || projectsResult[0].values.length === 0) {
|
|
1152
1194
|
return {
|
|
1195
|
+
success: true,
|
|
1153
1196
|
project_count: 0,
|
|
1154
1197
|
total_entries: 0,
|
|
1155
1198
|
projects: [],
|
|
@@ -1221,6 +1264,7 @@ function getAnalyticsTools(context) {
|
|
|
1221
1264
|
)
|
|
1222
1265
|
}));
|
|
1223
1266
|
return {
|
|
1267
|
+
success: true,
|
|
1224
1268
|
project_count: projects.length,
|
|
1225
1269
|
total_entries: totalEntries,
|
|
1226
1270
|
projects: projects.map((p) => ({
|
|
@@ -1320,10 +1364,28 @@ function getRelationshipTools(context) {
|
|
|
1320
1364
|
const input = LinkEntriesSchema.parse(params);
|
|
1321
1365
|
if (input.from_entry_id === input.to_entry_id) {
|
|
1322
1366
|
return {
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1367
|
+
...formatHandlerError(
|
|
1368
|
+
new ValidationError("Cannot link an entry to itself")
|
|
1369
|
+
),
|
|
1370
|
+
success: false
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
1373
|
+
const fromEntry = db.getEntryById(input.from_entry_id);
|
|
1374
|
+
if (!fromEntry || fromEntry.deletedAt) {
|
|
1375
|
+
return {
|
|
1376
|
+
...formatHandlerError(
|
|
1377
|
+
new ResourceNotFoundError("Entry", String(input.from_entry_id))
|
|
1378
|
+
),
|
|
1379
|
+
success: false
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
const toEntry = db.getEntryById(input.to_entry_id);
|
|
1383
|
+
if (!toEntry || toEntry.deletedAt) {
|
|
1384
|
+
return {
|
|
1385
|
+
...formatHandlerError(
|
|
1386
|
+
new ResourceNotFoundError("Entry", String(input.to_entry_id))
|
|
1387
|
+
),
|
|
1388
|
+
success: false
|
|
1327
1389
|
};
|
|
1328
1390
|
}
|
|
1329
1391
|
const existingRelationships = db.getRelationships(input.from_entry_id);
|
|
@@ -1358,12 +1420,13 @@ function getRelationshipTools(context) {
|
|
|
1358
1420
|
const isFkError = errMsg.includes("FOREIGN KEY constraint failed");
|
|
1359
1421
|
if (isFkError) {
|
|
1360
1422
|
return {
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1423
|
+
...formatHandlerError(
|
|
1424
|
+
new ResourceNotFoundError(
|
|
1425
|
+
"Entry",
|
|
1426
|
+
`from: ${String(input.from_entry_id)}, to: ${String(input.to_entry_id)}`
|
|
1427
|
+
)
|
|
1428
|
+
),
|
|
1429
|
+
success: false
|
|
1367
1430
|
};
|
|
1368
1431
|
}
|
|
1369
1432
|
}
|
|
@@ -1387,6 +1450,9 @@ function getRelationshipTools(context) {
|
|
|
1387
1450
|
const entry = db.getEntryById(input.entry_id);
|
|
1388
1451
|
if (!entry) {
|
|
1389
1452
|
return {
|
|
1453
|
+
...formatHandlerError(
|
|
1454
|
+
new ResourceNotFoundError("Entry", String(input.entry_id))
|
|
1455
|
+
),
|
|
1390
1456
|
success: false,
|
|
1391
1457
|
entry_count: 0,
|
|
1392
1458
|
relationship_count: 0,
|
|
@@ -2098,11 +2164,7 @@ ${e.content}
|
|
|
2098
2164
|
tags: e.tags,
|
|
2099
2165
|
significance: e.significanceType ?? void 0
|
|
2100
2166
|
}));
|
|
2101
|
-
const result = await exportEntriesToMarkdown(
|
|
2102
|
-
exportable,
|
|
2103
|
-
input.output_dir,
|
|
2104
|
-
db
|
|
2105
|
-
);
|
|
2167
|
+
const result = await exportEntriesToMarkdown(exportable, input.output_dir, db);
|
|
2106
2168
|
await sendProgress(progress, 3, 3, "Export complete");
|
|
2107
2169
|
return result;
|
|
2108
2170
|
} catch (err) {
|
|
@@ -2439,6 +2501,8 @@ var GitHubIssueOutputSchema = z.object({
|
|
|
2439
2501
|
}).extend(ErrorFieldsMixin.shape);
|
|
2440
2502
|
var GitHubIssueDetailsOutputSchema = GitHubIssueOutputSchema.extend({
|
|
2441
2503
|
body: z.string().nullable(),
|
|
2504
|
+
bodyTruncated: z.boolean().optional(),
|
|
2505
|
+
bodyFullLength: z.number().optional(),
|
|
2442
2506
|
labels: z.array(z.string()),
|
|
2443
2507
|
assignees: z.array(z.string()),
|
|
2444
2508
|
createdAt: z.string(),
|
|
@@ -2459,6 +2523,14 @@ var GitHubIssuesListOutputSchema = z.object({
|
|
|
2459
2523
|
}).extend(ErrorFieldsMixin.shape);
|
|
2460
2524
|
var GitHubIssueResultOutputSchema = z.object({
|
|
2461
2525
|
issue: GitHubIssueDetailsOutputSchema.optional(),
|
|
2526
|
+
comments: z.array(
|
|
2527
|
+
z.object({
|
|
2528
|
+
author: z.string(),
|
|
2529
|
+
body: z.string(),
|
|
2530
|
+
createdAt: z.string()
|
|
2531
|
+
})
|
|
2532
|
+
).optional(),
|
|
2533
|
+
commentCount: z.number().optional(),
|
|
2462
2534
|
owner: z.string().optional(),
|
|
2463
2535
|
repo: z.string().optional(),
|
|
2464
2536
|
detectedOwner: z.string().nullable().optional(),
|
|
@@ -2475,6 +2547,8 @@ var GitHubPullRequestOutputSchema = z.object({
|
|
|
2475
2547
|
}).extend(ErrorFieldsMixin.shape);
|
|
2476
2548
|
var GitHubPRDetailsOutputSchema = GitHubPullRequestOutputSchema.extend({
|
|
2477
2549
|
body: z.string().nullable(),
|
|
2550
|
+
bodyTruncated: z.boolean().optional(),
|
|
2551
|
+
bodyFullLength: z.number().optional(),
|
|
2478
2552
|
draft: z.boolean(),
|
|
2479
2553
|
headBranch: z.string(),
|
|
2480
2554
|
baseBranch: z.string(),
|
|
@@ -2539,7 +2613,9 @@ var StatusOptionOutputSchema = z.object({
|
|
|
2539
2613
|
var KanbanColumnOutputSchema = z.object({
|
|
2540
2614
|
status: z.string(),
|
|
2541
2615
|
statusOptionId: z.string(),
|
|
2542
|
-
items: z.array(KanbanItemOutputSchema)
|
|
2616
|
+
items: z.array(KanbanItemOutputSchema).optional(),
|
|
2617
|
+
itemCount: z.number().optional(),
|
|
2618
|
+
truncated: z.boolean().optional()
|
|
2543
2619
|
});
|
|
2544
2620
|
var KanbanBoardOutputSchema = z.object({
|
|
2545
2621
|
projectId: z.string().optional(),
|
|
@@ -2549,6 +2625,14 @@ var KanbanBoardOutputSchema = z.object({
|
|
|
2549
2625
|
statusOptions: z.array(StatusOptionOutputSchema).optional(),
|
|
2550
2626
|
columns: z.array(KanbanColumnOutputSchema).optional(),
|
|
2551
2627
|
totalItems: z.number().optional(),
|
|
2628
|
+
itemDirectory: z.array(
|
|
2629
|
+
z.object({
|
|
2630
|
+
id: z.string(),
|
|
2631
|
+
title: z.string(),
|
|
2632
|
+
status: z.string().nullable()
|
|
2633
|
+
})
|
|
2634
|
+
).optional(),
|
|
2635
|
+
summaryOnly: z.boolean().optional(),
|
|
2552
2636
|
owner: z.string().optional(),
|
|
2553
2637
|
detectedOwner: z.string().nullable().optional(),
|
|
2554
2638
|
detectedRepo: z.string().nullable().optional(),
|
|
@@ -2558,16 +2642,19 @@ var KanbanBoardOutputSchema = z.object({
|
|
|
2558
2642
|
instruction: z.string().optional()
|
|
2559
2643
|
}).extend(ErrorFieldsMixin.shape);
|
|
2560
2644
|
var MoveKanbanItemOutputSchema = z.object({
|
|
2561
|
-
success: z.boolean().optional(),
|
|
2562
2645
|
itemId: z.string().optional(),
|
|
2563
2646
|
newStatus: z.string().optional(),
|
|
2564
2647
|
projectNumber: z.number().optional(),
|
|
2565
|
-
message: z.string().optional(),
|
|
2566
|
-
error: z.string().optional(),
|
|
2567
|
-
requiresUserInput: z.boolean().optional(),
|
|
2568
|
-
hint: z.string().optional(),
|
|
2569
2648
|
availableStatuses: z.array(z.string()).optional()
|
|
2570
2649
|
}).extend(ErrorFieldsMixin.shape);
|
|
2650
|
+
var AddKanbanItemOutputSchema = z.object({
|
|
2651
|
+
itemId: z.string().optional(),
|
|
2652
|
+
projectNumber: z.number().optional()
|
|
2653
|
+
}).extend(ErrorFieldsMixin.shape);
|
|
2654
|
+
var DeleteKanbanItemOutputSchema = z.object({
|
|
2655
|
+
itemId: z.string().optional(),
|
|
2656
|
+
projectNumber: z.number().optional()
|
|
2657
|
+
}).extend(ErrorFieldsMixin.shape);
|
|
2571
2658
|
var CreateGitHubIssueWithEntryOutputSchema = z.object({
|
|
2572
2659
|
success: z.boolean().optional(),
|
|
2573
2660
|
issue: z.object({
|
|
@@ -2578,7 +2665,8 @@ var CreateGitHubIssueWithEntryOutputSchema = z.object({
|
|
|
2578
2665
|
project: z.object({
|
|
2579
2666
|
projectNumber: z.number(),
|
|
2580
2667
|
added: z.boolean(),
|
|
2581
|
-
message: z.string(),
|
|
2668
|
+
message: z.string().optional(),
|
|
2669
|
+
error: z.string().optional(),
|
|
2582
2670
|
initialStatus: z.object({
|
|
2583
2671
|
status: z.string(),
|
|
2584
2672
|
set: z.boolean()
|
|
@@ -2677,6 +2765,7 @@ var DeleteMilestoneOutputSchema = z.object({
|
|
|
2677
2765
|
instruction: z.string().optional()
|
|
2678
2766
|
}).extend(ErrorFieldsMixin.shape);
|
|
2679
2767
|
var RepoInsightsOutputSchema = z.object({
|
|
2768
|
+
success: z.boolean().optional(),
|
|
2680
2769
|
owner: z.string().optional(),
|
|
2681
2770
|
repo: z.string().optional(),
|
|
2682
2771
|
section: z.string().optional(),
|
|
@@ -2858,7 +2947,7 @@ function getGitHubReadTools(context) {
|
|
|
2858
2947
|
owner: z.string().optional(),
|
|
2859
2948
|
repo: z.string().optional(),
|
|
2860
2949
|
state: z.enum(["open", "closed", "all"]).optional().default("open"),
|
|
2861
|
-
limit: z.number().optional().default(20)
|
|
2950
|
+
limit: z.number().max(MAX_QUERY_LIMIT).optional().default(20)
|
|
2862
2951
|
}).parse(params);
|
|
2863
2952
|
const resolved = await resolveOwnerRepo(
|
|
2864
2953
|
context,
|
|
@@ -2908,7 +2997,7 @@ function getGitHubReadTools(context) {
|
|
|
2908
2997
|
owner: z.string().optional(),
|
|
2909
2998
|
repo: z.string().optional(),
|
|
2910
2999
|
state: z.enum(["open", "closed", "all"]).optional().default("open"),
|
|
2911
|
-
limit: z.number().optional().default(20)
|
|
3000
|
+
limit: z.number().max(MAX_QUERY_LIMIT).optional().default(20)
|
|
2912
3001
|
}).parse(params);
|
|
2913
3002
|
const resolved = await resolveOwnerRepo(
|
|
2914
3003
|
context,
|
|
@@ -2943,7 +3032,11 @@ function getGitHubReadTools(context) {
|
|
|
2943
3032
|
inputSchema: z.object({
|
|
2944
3033
|
issue_number: z.number(),
|
|
2945
3034
|
owner: z.string().optional().describe("LEAVE EMPTY to auto-detect from git"),
|
|
2946
|
-
repo: z.string().optional().describe("LEAVE EMPTY to auto-detect from git")
|
|
3035
|
+
repo: z.string().optional().describe("LEAVE EMPTY to auto-detect from git"),
|
|
3036
|
+
truncate_body: relaxedNumber().optional().default(800).describe(
|
|
3037
|
+
"Max characters for body text (0 = full body, default 800). Reduces token usage."
|
|
3038
|
+
),
|
|
3039
|
+
include_comments: z.boolean().optional().default(false).describe("Include issue comments (default false). Each comment adds tokens.")
|
|
2947
3040
|
}),
|
|
2948
3041
|
outputSchema: GitHubIssueResultOutputSchema,
|
|
2949
3042
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
@@ -2952,7 +3045,9 @@ function getGitHubReadTools(context) {
|
|
|
2952
3045
|
const input = z.object({
|
|
2953
3046
|
issue_number: z.number(),
|
|
2954
3047
|
owner: z.string().optional(),
|
|
2955
|
-
repo: z.string().optional()
|
|
3048
|
+
repo: z.string().optional(),
|
|
3049
|
+
truncate_body: z.number().optional().default(800),
|
|
3050
|
+
include_comments: z.boolean().optional().default(false)
|
|
2956
3051
|
}).parse(params);
|
|
2957
3052
|
const resolved = await resolveOwnerRepo(context, input, "is this issue from");
|
|
2958
3053
|
if ("error" in resolved) return resolved.response;
|
|
@@ -2975,8 +3070,30 @@ function getGitHubReadTools(context) {
|
|
|
2975
3070
|
detectedRepo: resolved.detectedRepo
|
|
2976
3071
|
};
|
|
2977
3072
|
}
|
|
3073
|
+
const truncateBody = input.truncate_body;
|
|
3074
|
+
let bodyTruncated = false;
|
|
3075
|
+
let bodyFullLength;
|
|
3076
|
+
if (truncateBody > 0 && issue.body && issue.body.length > truncateBody) {
|
|
3077
|
+
bodyFullLength = issue.body.length;
|
|
3078
|
+
const remaining = issue.body.length - truncateBody;
|
|
3079
|
+
issue.body = issue.body.slice(0, truncateBody) + `
|
|
3080
|
+
[Truncated. Re-run with truncate_body: 0 to view remaining ${String(remaining)} chars]`;
|
|
3081
|
+
bodyTruncated = true;
|
|
3082
|
+
}
|
|
3083
|
+
let comments;
|
|
3084
|
+
if (input.include_comments) {
|
|
3085
|
+
comments = await resolved.github.getIssueComments(
|
|
3086
|
+
resolved.owner,
|
|
3087
|
+
resolved.repo,
|
|
3088
|
+
input.issue_number
|
|
3089
|
+
);
|
|
3090
|
+
}
|
|
2978
3091
|
return {
|
|
2979
|
-
issue
|
|
3092
|
+
issue: {
|
|
3093
|
+
...issue,
|
|
3094
|
+
...bodyTruncated ? { bodyTruncated: true, bodyFullLength } : {}
|
|
3095
|
+
},
|
|
3096
|
+
...comments ? { comments, commentCount: comments.length } : {},
|
|
2980
3097
|
owner: resolved.owner,
|
|
2981
3098
|
repo: resolved.repo,
|
|
2982
3099
|
detectedOwner: resolved.detectedOwner,
|
|
@@ -2995,7 +3112,10 @@ function getGitHubReadTools(context) {
|
|
|
2995
3112
|
inputSchema: z.object({
|
|
2996
3113
|
pr_number: z.number(),
|
|
2997
3114
|
owner: z.string().optional().describe("LEAVE EMPTY to auto-detect from git"),
|
|
2998
|
-
repo: z.string().optional().describe("LEAVE EMPTY to auto-detect from git")
|
|
3115
|
+
repo: z.string().optional().describe("LEAVE EMPTY to auto-detect from git"),
|
|
3116
|
+
truncate_body: relaxedNumber().optional().default(800).describe(
|
|
3117
|
+
"Max characters for body text (0 = full body, default 800). Reduces token usage."
|
|
3118
|
+
)
|
|
2999
3119
|
}),
|
|
3000
3120
|
outputSchema: GitHubPRResultOutputSchema,
|
|
3001
3121
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
@@ -3004,7 +3124,8 @@ function getGitHubReadTools(context) {
|
|
|
3004
3124
|
const input = z.object({
|
|
3005
3125
|
pr_number: z.number(),
|
|
3006
3126
|
owner: z.string().optional(),
|
|
3007
|
-
repo: z.string().optional()
|
|
3127
|
+
repo: z.string().optional(),
|
|
3128
|
+
truncate_body: z.number().optional().default(800)
|
|
3008
3129
|
}).parse(params);
|
|
3009
3130
|
const resolved = await resolveOwnerRepo(context, input, "is this PR from");
|
|
3010
3131
|
if ("error" in resolved) return resolved.response;
|
|
@@ -3027,8 +3148,21 @@ function getGitHubReadTools(context) {
|
|
|
3027
3148
|
detectedRepo: resolved.detectedRepo
|
|
3028
3149
|
};
|
|
3029
3150
|
}
|
|
3151
|
+
const truncateBody = input.truncate_body;
|
|
3152
|
+
let bodyTruncated = false;
|
|
3153
|
+
let bodyFullLength;
|
|
3154
|
+
if (truncateBody > 0 && pullRequest.body && pullRequest.body.length > truncateBody) {
|
|
3155
|
+
bodyFullLength = pullRequest.body.length;
|
|
3156
|
+
const remaining = pullRequest.body.length - truncateBody;
|
|
3157
|
+
pullRequest.body = pullRequest.body.slice(0, truncateBody) + `
|
|
3158
|
+
[Truncated. Re-run with truncate_body: 0 to view remaining ${String(remaining)} chars]`;
|
|
3159
|
+
bodyTruncated = true;
|
|
3160
|
+
}
|
|
3030
3161
|
return {
|
|
3031
|
-
pullRequest
|
|
3162
|
+
pullRequest: {
|
|
3163
|
+
...pullRequest,
|
|
3164
|
+
...bodyTruncated ? { bodyTruncated: true, bodyFullLength } : {}
|
|
3165
|
+
},
|
|
3032
3166
|
owner: resolved.owner,
|
|
3033
3167
|
repo: resolved.repo,
|
|
3034
3168
|
detectedOwner: resolved.detectedOwner,
|
|
@@ -3096,7 +3230,13 @@ function getKanbanTools(context) {
|
|
|
3096
3230
|
inputSchema: z.object({
|
|
3097
3231
|
project_number: z.number().optional().describe("GitHub Project number (optional if repo is registered)"),
|
|
3098
3232
|
owner: z.string().optional().describe("Project owner - LEAVE EMPTY to auto-detect"),
|
|
3099
|
-
repo: z.string().optional().describe("Repository name - LEAVE EMPTY to auto-detect")
|
|
3233
|
+
repo: z.string().optional().describe("Repository name - LEAVE EMPTY to auto-detect"),
|
|
3234
|
+
summary_only: z.boolean().optional().default(false).describe(
|
|
3235
|
+
"Return column summaries only (name + itemCount), omitting individual items. Saves ~80% tokens."
|
|
3236
|
+
),
|
|
3237
|
+
item_limit: relaxedNumber().optional().default(25).describe(
|
|
3238
|
+
"Maximum items per column (default 25, max 100). Set to 0 for summary_only behavior."
|
|
3239
|
+
)
|
|
3100
3240
|
}),
|
|
3101
3241
|
outputSchema: KanbanBoardOutputSchema,
|
|
3102
3242
|
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true },
|
|
@@ -3105,7 +3245,9 @@ function getKanbanTools(context) {
|
|
|
3105
3245
|
const input = z.object({
|
|
3106
3246
|
project_number: z.number().optional(),
|
|
3107
3247
|
owner: z.string().optional(),
|
|
3108
|
-
repo: z.string().optional()
|
|
3248
|
+
repo: z.string().optional(),
|
|
3249
|
+
summary_only: z.boolean().optional().default(false),
|
|
3250
|
+
item_limit: z.number().max(100).optional().default(25)
|
|
3109
3251
|
}).parse(params);
|
|
3110
3252
|
const resolved = await resolveOwner(context, input.owner);
|
|
3111
3253
|
if ("error" in resolved) return resolved.response;
|
|
@@ -3144,7 +3286,44 @@ function getKanbanTools(context) {
|
|
|
3144
3286
|
recoverable: true
|
|
3145
3287
|
};
|
|
3146
3288
|
}
|
|
3147
|
-
|
|
3289
|
+
const summaryOnly = input.summary_only || input.item_limit === 0;
|
|
3290
|
+
if (summaryOnly) {
|
|
3291
|
+
const summaryColumns = board.columns.map((col) => ({
|
|
3292
|
+
status: col.status,
|
|
3293
|
+
statusOptionId: col.statusOptionId,
|
|
3294
|
+
items: [],
|
|
3295
|
+
itemCount: col.items.length
|
|
3296
|
+
}));
|
|
3297
|
+
const itemDirectory = board.columns.flatMap(
|
|
3298
|
+
(col) => col.items.map((item) => ({
|
|
3299
|
+
id: item.id,
|
|
3300
|
+
title: item.title,
|
|
3301
|
+
status: item.status
|
|
3302
|
+
}))
|
|
3303
|
+
);
|
|
3304
|
+
return {
|
|
3305
|
+
...board,
|
|
3306
|
+
columns: summaryColumns,
|
|
3307
|
+
summaryOnly: true,
|
|
3308
|
+
itemDirectory
|
|
3309
|
+
};
|
|
3310
|
+
}
|
|
3311
|
+
const itemLimit = input.item_limit;
|
|
3312
|
+
const truncatedColumns = board.columns.map((col) => {
|
|
3313
|
+
if (col.items.length <= itemLimit) {
|
|
3314
|
+
return { ...col, itemCount: col.items.length };
|
|
3315
|
+
}
|
|
3316
|
+
return {
|
|
3317
|
+
...col,
|
|
3318
|
+
items: col.items.slice(0, itemLimit),
|
|
3319
|
+
itemCount: col.items.length,
|
|
3320
|
+
truncated: true
|
|
3321
|
+
};
|
|
3322
|
+
});
|
|
3323
|
+
return {
|
|
3324
|
+
...board,
|
|
3325
|
+
columns: truncatedColumns
|
|
3326
|
+
};
|
|
3148
3327
|
} catch (err) {
|
|
3149
3328
|
return formatHandlerError(err);
|
|
3150
3329
|
}
|
|
@@ -3237,6 +3416,155 @@ function getKanbanTools(context) {
|
|
|
3237
3416
|
return formatHandlerError(err);
|
|
3238
3417
|
}
|
|
3239
3418
|
}
|
|
3419
|
+
},
|
|
3420
|
+
{
|
|
3421
|
+
name: "add_kanban_item",
|
|
3422
|
+
title: "Add Kanban Item",
|
|
3423
|
+
description: "Add an existing GitHub Issue or Pull Request to a Kanban board (GitHub Project v2). Returns the project item ID on success.",
|
|
3424
|
+
group: "github",
|
|
3425
|
+
inputSchema: z.object({
|
|
3426
|
+
project_number: z.number().optional().describe("GitHub Project number (optional if repo is registered)"),
|
|
3427
|
+
issue_number: z.number().describe("The number of the issue or PR to add"),
|
|
3428
|
+
owner: z.string().optional().describe("Repository owner - LEAVE EMPTY to auto-detect"),
|
|
3429
|
+
repo: z.string().optional().describe("Repository name - LEAVE EMPTY to auto-detect")
|
|
3430
|
+
}),
|
|
3431
|
+
outputSchema: AddKanbanItemOutputSchema,
|
|
3432
|
+
annotations: { readOnlyHint: false, idempotentHint: true, openWorldHint: true },
|
|
3433
|
+
handler: async (params) => {
|
|
3434
|
+
try {
|
|
3435
|
+
const input = z.object({
|
|
3436
|
+
project_number: z.number().optional(),
|
|
3437
|
+
issue_number: z.number(),
|
|
3438
|
+
owner: z.string().optional(),
|
|
3439
|
+
repo: z.string().optional()
|
|
3440
|
+
}).parse(params);
|
|
3441
|
+
const resolved = await resolveOwnerRepo(context, input);
|
|
3442
|
+
if ("error" in resolved) return resolved.response;
|
|
3443
|
+
const projectNum = resolveProjectNumber(
|
|
3444
|
+
context,
|
|
3445
|
+
resolved.repo,
|
|
3446
|
+
input.project_number
|
|
3447
|
+
);
|
|
3448
|
+
if (projectNum === void 0) {
|
|
3449
|
+
return {
|
|
3450
|
+
success: false,
|
|
3451
|
+
error: "project_number is required and could not be resolved from registry. Please supply it explicitly.",
|
|
3452
|
+
code: "VALIDATION_ERROR",
|
|
3453
|
+
category: "validation",
|
|
3454
|
+
recoverable: true
|
|
3455
|
+
};
|
|
3456
|
+
}
|
|
3457
|
+
const issueDetails = await resolved.github.getIssue(
|
|
3458
|
+
resolved.owner,
|
|
3459
|
+
resolved.repo,
|
|
3460
|
+
input.issue_number
|
|
3461
|
+
);
|
|
3462
|
+
if (!issueDetails?.nodeId) {
|
|
3463
|
+
return {
|
|
3464
|
+
success: false,
|
|
3465
|
+
error: `Issue or PR #${String(input.issue_number)} not found or lacks a nodeId`,
|
|
3466
|
+
code: "RESOURCE_NOT_FOUND",
|
|
3467
|
+
category: "resource",
|
|
3468
|
+
recoverable: true
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3471
|
+
const board = await resolved.github.getProjectKanban(
|
|
3472
|
+
resolved.owner,
|
|
3473
|
+
projectNum,
|
|
3474
|
+
resolved.repo
|
|
3475
|
+
);
|
|
3476
|
+
if (!board) {
|
|
3477
|
+
return {
|
|
3478
|
+
success: false,
|
|
3479
|
+
error: `Project #${String(projectNum)} not found`,
|
|
3480
|
+
code: "RESOURCE_NOT_FOUND",
|
|
3481
|
+
category: "resource",
|
|
3482
|
+
recoverable: true
|
|
3483
|
+
};
|
|
3484
|
+
}
|
|
3485
|
+
const result = await resolved.github.addProjectItem(
|
|
3486
|
+
board.projectId,
|
|
3487
|
+
issueDetails.nodeId
|
|
3488
|
+
);
|
|
3489
|
+
return {
|
|
3490
|
+
success: result.success,
|
|
3491
|
+
itemId: result.itemId,
|
|
3492
|
+
projectNumber: projectNum,
|
|
3493
|
+
message: result.success ? `Added Issue/PR #${String(input.issue_number)} to Project #${projectNum}` : void 0,
|
|
3494
|
+
error: result.error
|
|
3495
|
+
};
|
|
3496
|
+
} catch (err) {
|
|
3497
|
+
return formatHandlerError(err);
|
|
3498
|
+
}
|
|
3499
|
+
}
|
|
3500
|
+
},
|
|
3501
|
+
{
|
|
3502
|
+
name: "delete_kanban_item",
|
|
3503
|
+
title: "Delete Kanban Item",
|
|
3504
|
+
description: "Remove an item from a GitHub Kanban board cleanly. This untethers it from the project but does NOT close or delete the underlying Issue/PR.",
|
|
3505
|
+
group: "github",
|
|
3506
|
+
inputSchema: z.object({
|
|
3507
|
+
project_number: z.number().optional().describe("GitHub Project number (optional if repo is registered)"),
|
|
3508
|
+
item_id: z.string().describe("The project item ID to remove (from get_kanban_board)"),
|
|
3509
|
+
owner: z.string().optional().describe("Project owner - LEAVE EMPTY to auto-detect"),
|
|
3510
|
+
repo: z.string().optional().describe("Repository name - LEAVE EMPTY to auto-detect")
|
|
3511
|
+
}),
|
|
3512
|
+
outputSchema: DeleteKanbanItemOutputSchema,
|
|
3513
|
+
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: true },
|
|
3514
|
+
handler: async (params) => {
|
|
3515
|
+
try {
|
|
3516
|
+
const input = z.object({
|
|
3517
|
+
project_number: z.number().optional(),
|
|
3518
|
+
item_id: z.string(),
|
|
3519
|
+
owner: z.string().optional(),
|
|
3520
|
+
repo: z.string().optional()
|
|
3521
|
+
}).parse(params);
|
|
3522
|
+
const resolved = await resolveOwner(context, input.owner);
|
|
3523
|
+
if ("error" in resolved) return resolved.response;
|
|
3524
|
+
const effectiveRepo = input.repo ?? resolved.repo;
|
|
3525
|
+
const projectNum = resolveProjectNumber(
|
|
3526
|
+
context,
|
|
3527
|
+
effectiveRepo,
|
|
3528
|
+
input.project_number
|
|
3529
|
+
);
|
|
3530
|
+
if (projectNum === void 0) {
|
|
3531
|
+
return {
|
|
3532
|
+
success: false,
|
|
3533
|
+
error: "project_number is required and could not be resolved from registry. Please supply it explicitly.",
|
|
3534
|
+
code: "VALIDATION_ERROR",
|
|
3535
|
+
category: "validation",
|
|
3536
|
+
recoverable: true
|
|
3537
|
+
};
|
|
3538
|
+
}
|
|
3539
|
+
const board = await resolved.github.getProjectKanban(
|
|
3540
|
+
resolved.owner,
|
|
3541
|
+
projectNum,
|
|
3542
|
+
effectiveRepo
|
|
3543
|
+
);
|
|
3544
|
+
if (!board) {
|
|
3545
|
+
return {
|
|
3546
|
+
success: false,
|
|
3547
|
+
error: `Project #${String(projectNum)} not found`,
|
|
3548
|
+
code: "RESOURCE_NOT_FOUND",
|
|
3549
|
+
category: "resource",
|
|
3550
|
+
recoverable: true
|
|
3551
|
+
};
|
|
3552
|
+
}
|
|
3553
|
+
const result = await resolved.github.deleteProjectItem(
|
|
3554
|
+
board.projectId,
|
|
3555
|
+
input.item_id
|
|
3556
|
+
);
|
|
3557
|
+
return {
|
|
3558
|
+
success: result.success,
|
|
3559
|
+
itemId: input.item_id,
|
|
3560
|
+
projectNumber: projectNum,
|
|
3561
|
+
message: result.success ? `Deleted item ${input.item_id} from Project #${projectNum}` : void 0,
|
|
3562
|
+
error: result.error
|
|
3563
|
+
};
|
|
3564
|
+
} catch (err) {
|
|
3565
|
+
return formatHandlerError(err);
|
|
3566
|
+
}
|
|
3567
|
+
}
|
|
3240
3568
|
}
|
|
3241
3569
|
];
|
|
3242
3570
|
}
|
|
@@ -3294,7 +3622,11 @@ function getGitHubIssueTools(context) {
|
|
|
3294
3622
|
if (!issue) {
|
|
3295
3623
|
return {
|
|
3296
3624
|
success: false,
|
|
3297
|
-
error: "Failed to create GitHub issue. Check GITHUB_TOKEN permissions."
|
|
3625
|
+
error: "Failed to create GitHub issue. Check GITHUB_TOKEN permissions.",
|
|
3626
|
+
code: "API_ERROR",
|
|
3627
|
+
category: "api",
|
|
3628
|
+
suggestion: "Verify GitHub token has write access to issues.",
|
|
3629
|
+
recoverable: true
|
|
3298
3630
|
};
|
|
3299
3631
|
}
|
|
3300
3632
|
const projectNumber = resolveProjectNumber(
|
|
@@ -3453,13 +3785,21 @@ Description: ${input.body.slice(0, 200)}${input.body.length > 200 ? "..." : ""}`
|
|
|
3453
3785
|
if (!issueDetails) {
|
|
3454
3786
|
return {
|
|
3455
3787
|
success: false,
|
|
3456
|
-
error: `Issue #${String(input.issue_number)} not found
|
|
3788
|
+
error: `Issue #${String(input.issue_number)} not found`,
|
|
3789
|
+
code: "RESOURCE_NOT_FOUND",
|
|
3790
|
+
category: "resource",
|
|
3791
|
+
suggestion: "Verify the issue number exists in this repository.",
|
|
3792
|
+
recoverable: true
|
|
3457
3793
|
};
|
|
3458
3794
|
}
|
|
3459
3795
|
if (issueDetails.state === "CLOSED") {
|
|
3460
3796
|
return {
|
|
3461
|
-
|
|
3462
|
-
|
|
3797
|
+
...formatHandlerError(
|
|
3798
|
+
new ValidationError(
|
|
3799
|
+
`Issue #${String(input.issue_number)} is already closed`
|
|
3800
|
+
)
|
|
3801
|
+
),
|
|
3802
|
+
success: false
|
|
3463
3803
|
};
|
|
3464
3804
|
}
|
|
3465
3805
|
const result = await resolved.github.closeIssue(
|
|
@@ -3471,7 +3811,11 @@ Description: ${input.body.slice(0, 200)}${input.body.length > 200 ? "..." : ""}`
|
|
|
3471
3811
|
if (!result) {
|
|
3472
3812
|
return {
|
|
3473
3813
|
success: false,
|
|
3474
|
-
error: "Failed to close GitHub issue. Check GITHUB_TOKEN permissions."
|
|
3814
|
+
error: "Failed to close GitHub issue. Check GITHUB_TOKEN permissions.",
|
|
3815
|
+
code: "API_ERROR",
|
|
3816
|
+
category: "api",
|
|
3817
|
+
suggestion: "Verify GitHub token has write access to issues.",
|
|
3818
|
+
recoverable: true
|
|
3475
3819
|
};
|
|
3476
3820
|
}
|
|
3477
3821
|
let kanbanResult;
|
|
@@ -3630,10 +3974,12 @@ function isResourceError(result) {
|
|
|
3630
3974
|
}
|
|
3631
3975
|
var DEFAULT_BRIEFING_CONFIG = {
|
|
3632
3976
|
entryCount: 3,
|
|
3977
|
+
summaryCount: 1,
|
|
3633
3978
|
includeTeam: false,
|
|
3634
3979
|
issueCount: 0,
|
|
3635
3980
|
prCount: 0,
|
|
3636
3981
|
prStatusBreakdown: false,
|
|
3982
|
+
milestoneCount: 3,
|
|
3637
3983
|
workflowCount: 0,
|
|
3638
3984
|
workflowStatusBreakdown: false,
|
|
3639
3985
|
copilotReviews: false
|
|
@@ -4013,6 +4359,7 @@ function getGitHubInsightsTools(context) {
|
|
|
4013
4359
|
const repo = resolved.repo;
|
|
4014
4360
|
const section = input.sections;
|
|
4015
4361
|
const result = {
|
|
4362
|
+
success: true,
|
|
4016
4363
|
owner,
|
|
4017
4364
|
repo,
|
|
4018
4365
|
section
|
|
@@ -4373,7 +4720,7 @@ var TeamCreateEntrySchemaMcp = z.object({
|
|
|
4373
4720
|
author: z.string().optional()
|
|
4374
4721
|
});
|
|
4375
4722
|
var TeamGetRecentSchema = z.object({
|
|
4376
|
-
limit: z.number().max(500).optional().default(10)
|
|
4723
|
+
limit: z.number().min(1).max(500).optional().default(10)
|
|
4377
4724
|
});
|
|
4378
4725
|
var TeamGetRecentSchemaMcp = z.object({
|
|
4379
4726
|
limit: relaxedNumber().optional().default(10)
|
|
@@ -4600,6 +4947,10 @@ var TeamSemanticSearchSchema = z.object({
|
|
|
4600
4947
|
entry_id: z.number().optional().describe("Find entries related to this entry ID"),
|
|
4601
4948
|
limit: z.number().max(500).optional().default(10),
|
|
4602
4949
|
similarity_threshold: z.number().optional().default(0.25),
|
|
4950
|
+
tags: z.array(z.string()).optional(),
|
|
4951
|
+
entry_type: z.enum(ENTRY_TYPES).optional(),
|
|
4952
|
+
start_date: z.string().regex(DATE_FORMAT_REGEX, DATE_FORMAT_MESSAGE).optional(),
|
|
4953
|
+
end_date: z.string().regex(DATE_FORMAT_REGEX, DATE_FORMAT_MESSAGE).optional(),
|
|
4603
4954
|
hint_on_empty: z.boolean().optional().default(true).describe("Include hint when no results found (default: true)")
|
|
4604
4955
|
});
|
|
4605
4956
|
var TeamSemanticSearchSchemaMcp = z.object({
|
|
@@ -4607,6 +4958,10 @@ var TeamSemanticSearchSchemaMcp = z.object({
|
|
|
4607
4958
|
entry_id: relaxedNumber().optional().describe("Find entries related to this entry ID"),
|
|
4608
4959
|
limit: relaxedNumber().optional().default(10),
|
|
4609
4960
|
similarity_threshold: relaxedNumber().optional().default(0.25),
|
|
4961
|
+
tags: z.array(z.string()).optional(),
|
|
4962
|
+
entry_type: z.string().optional(),
|
|
4963
|
+
start_date: z.string().optional(),
|
|
4964
|
+
end_date: z.string().optional(),
|
|
4610
4965
|
hint_on_empty: z.boolean().optional().default(true).describe("Include hint when no results found (default: true)")
|
|
4611
4966
|
});
|
|
4612
4967
|
var TeamAddToVectorIndexSchema = z.object({
|
|
@@ -4857,11 +5212,12 @@ function getTeamSearchTools(context) {
|
|
|
4857
5212
|
return { ...TEAM_DB_ERROR_RESPONSE };
|
|
4858
5213
|
}
|
|
4859
5214
|
const { query, tags, limit } = TeamSearchSchema.parse(params);
|
|
5215
|
+
const searchLimit = tags && tags.length > 0 ? Math.max(limit * 5, 50) : limit;
|
|
4860
5216
|
let entries;
|
|
4861
5217
|
if (query) {
|
|
4862
|
-
entries = teamDb.searchEntries(query, { limit });
|
|
5218
|
+
entries = teamDb.searchEntries(query, { limit: searchLimit });
|
|
4863
5219
|
} else {
|
|
4864
|
-
entries = teamDb.getRecentEntries(
|
|
5220
|
+
entries = teamDb.getRecentEntries(searchLimit);
|
|
4865
5221
|
}
|
|
4866
5222
|
if (tags && tags.length > 0) {
|
|
4867
5223
|
const entryIds = entries.map((e) => e.id);
|
|
@@ -4887,6 +5243,7 @@ function getTeamSearchTools(context) {
|
|
|
4887
5243
|
});
|
|
4888
5244
|
}
|
|
4889
5245
|
}
|
|
5246
|
+
entries = entries.slice(0, limit);
|
|
4890
5247
|
const authorMap = batchFetchAuthors(
|
|
4891
5248
|
teamDb,
|
|
4892
5249
|
entries.map((e) => e.id)
|
|
@@ -4895,7 +5252,7 @@ function getTeamSearchTools(context) {
|
|
|
4895
5252
|
...e,
|
|
4896
5253
|
author: authorMap.get(e.id) ?? null
|
|
4897
5254
|
}));
|
|
4898
|
-
return { entries: enriched, count: enriched.length };
|
|
5255
|
+
return { success: true, entries: enriched, count: enriched.length };
|
|
4899
5256
|
} catch (err) {
|
|
4900
5257
|
return formatHandlerError(err);
|
|
4901
5258
|
}
|
|
@@ -4938,7 +5295,7 @@ function getTeamSearchTools(context) {
|
|
|
4938
5295
|
...e,
|
|
4939
5296
|
author: authorMap.get(e.id) ?? null
|
|
4940
5297
|
}));
|
|
4941
|
-
return { entries: enriched, count: enriched.length };
|
|
5298
|
+
return { success: true, entries: enriched, count: enriched.length };
|
|
4942
5299
|
} catch (err) {
|
|
4943
5300
|
return formatHandlerError(err);
|
|
4944
5301
|
}
|
|
@@ -5347,6 +5704,17 @@ function getTeamRelationshipTools(context) {
|
|
|
5347
5704
|
const { entry_id, tag, depth } = TeamVisualizeRelationshipsSchema.parse(params);
|
|
5348
5705
|
let entryIds = [];
|
|
5349
5706
|
if (entry_id !== void 0) {
|
|
5707
|
+
const fromEntry = teamDb.getEntryById(entry_id);
|
|
5708
|
+
if (!fromEntry) {
|
|
5709
|
+
return {
|
|
5710
|
+
success: false,
|
|
5711
|
+
error: `Team entry ${String(entry_id)} not found`,
|
|
5712
|
+
code: "RESOURCE_NOT_FOUND",
|
|
5713
|
+
category: "resource",
|
|
5714
|
+
suggestion: "Verify the team entry ID and try again",
|
|
5715
|
+
recoverable: true
|
|
5716
|
+
};
|
|
5717
|
+
}
|
|
5350
5718
|
entryIds = [entry_id];
|
|
5351
5719
|
const visited = new Set(entryIds);
|
|
5352
5720
|
let frontier = [...entryIds];
|
|
@@ -5792,17 +6160,19 @@ function getTeamVectorTools(context) {
|
|
|
5792
6160
|
count: 0
|
|
5793
6161
|
};
|
|
5794
6162
|
}
|
|
6163
|
+
const hasFilters = input.tags !== void 0 || input.entry_type !== void 0 || input.start_date !== void 0 || input.end_date !== void 0;
|
|
6164
|
+
const internalLimit = hasFilters ? Math.min(Math.max(input.limit * 10, 100), 1e3) : input.limit * 2;
|
|
5795
6165
|
let results;
|
|
5796
6166
|
if (input.entry_id !== void 0) {
|
|
5797
6167
|
results = await teamVectorManager.searchByEntryId(
|
|
5798
6168
|
input.entry_id,
|
|
5799
|
-
|
|
6169
|
+
internalLimit,
|
|
5800
6170
|
input.similarity_threshold ?? 0.25
|
|
5801
6171
|
);
|
|
5802
6172
|
} else {
|
|
5803
6173
|
results = await teamVectorManager.search(
|
|
5804
6174
|
input.query ?? "",
|
|
5805
|
-
|
|
6175
|
+
internalLimit,
|
|
5806
6176
|
input.similarity_threshold ?? 0.25
|
|
5807
6177
|
);
|
|
5808
6178
|
}
|
|
@@ -5814,12 +6184,24 @@ function getTeamVectorTools(context) {
|
|
|
5814
6184
|
if (!entry) return null;
|
|
5815
6185
|
if (input.entry_id !== void 0 && entry.id === input.entry_id)
|
|
5816
6186
|
return null;
|
|
6187
|
+
if (!passMetadataFilters(
|
|
6188
|
+
entry,
|
|
6189
|
+
{
|
|
6190
|
+
tags: input.tags,
|
|
6191
|
+
entryType: input.entry_type,
|
|
6192
|
+
startDate: input.start_date,
|
|
6193
|
+
endDate: input.end_date
|
|
6194
|
+
},
|
|
6195
|
+
teamDb
|
|
6196
|
+
)) {
|
|
6197
|
+
return null;
|
|
6198
|
+
}
|
|
5817
6199
|
return {
|
|
5818
6200
|
...entry,
|
|
5819
6201
|
author: authorMap.get(r.entryId) ?? null,
|
|
5820
6202
|
similarity: Math.round(r.score * 100) / 100
|
|
5821
6203
|
};
|
|
5822
|
-
}).filter((e) => e !== null);
|
|
6204
|
+
}).filter((e) => e !== null).slice(0, input.limit);
|
|
5823
6205
|
const stats = teamVectorManager.getStats();
|
|
5824
6206
|
const isIndexEmpty = stats.itemCount === 0;
|
|
5825
6207
|
const includeHint = input.hint_on_empty ?? true;
|
|
@@ -5827,6 +6209,7 @@ function getTeamVectorTools(context) {
|
|
|
5827
6209
|
const allNoise = entries.length > 0 && bestSimilarity < QUALITY_FLOOR;
|
|
5828
6210
|
const hint = isIndexEmpty && includeHint ? "No entries in team vector index. Use team_rebuild_vector_index to index existing entries." : entries.length === 0 && includeHint ? `No entries matched your query above the similarity threshold (${String(input.similarity_threshold ?? 0.25)}). Try lowering similarity_threshold (e.g., 0.15) for broader matches.` : allNoise ? `Results may be noise \u2014 best similarity (${String(bestSimilarity)}) is below quality floor (${String(QUALITY_FLOOR)}). Try a more specific query or raise similarity_threshold to filter weak matches.` : void 0;
|
|
5829
6211
|
return {
|
|
6212
|
+
success: true,
|
|
5830
6213
|
query: input.query,
|
|
5831
6214
|
...input.entry_id !== void 0 ? { entryId: input.entry_id } : {},
|
|
5832
6215
|
entries,
|
|
@@ -6021,6 +6404,8 @@ var METHOD_ALIASES = {
|
|
|
6021
6404
|
context: "getGithubContext",
|
|
6022
6405
|
kanban: "getKanbanBoard",
|
|
6023
6406
|
moveKanban: "moveKanbanItem",
|
|
6407
|
+
addKanban: "addKanbanItem",
|
|
6408
|
+
deleteKanban: "deleteKanbanItem",
|
|
6024
6409
|
milestones: "getGithubMilestones",
|
|
6025
6410
|
milestone: "getGithubMilestone",
|
|
6026
6411
|
createMilestone: "createGithubMilestone",
|
|
@@ -6095,6 +6480,7 @@ var GROUP_EXAMPLES = {
|
|
|
6095
6480
|
'mj.github.getGithubIssues({ state: "open" })',
|
|
6096
6481
|
'mj.github.getGithubPrs({ state: "open" })',
|
|
6097
6482
|
"mj.github.getKanbanBoard({ project_number: 1 })",
|
|
6483
|
+
"mj.github.addKanbanItem({ project_number: 1, issue_number: 123 })",
|
|
6098
6484
|
"mj.github.getGithubMilestones()",
|
|
6099
6485
|
"mj.github.getRepoInsights()"
|
|
6100
6486
|
],
|
|
@@ -6143,7 +6529,9 @@ var POSITIONAL_PARAM_MAP = {
|
|
|
6143
6529
|
getGithubIssue: "issue_number",
|
|
6144
6530
|
getGithubPr: "pr_number",
|
|
6145
6531
|
getKanbanBoard: "project_number",
|
|
6146
|
-
moveKanbanItem: ["item_id", "
|
|
6532
|
+
moveKanbanItem: ["item_id", "target_status"],
|
|
6533
|
+
addKanbanItem: "issue_number",
|
|
6534
|
+
deleteKanbanItem: "item_id",
|
|
6147
6535
|
getGithubMilestone: "milestone_number",
|
|
6148
6536
|
createGithubMilestone: "title",
|
|
6149
6537
|
updateGithubMilestone: "milestone_number",
|
|
@@ -6377,8 +6765,8 @@ var DEFAULT_SECURITY_CONFIG = {
|
|
|
6377
6765
|
maxCodeLength: 50 * 1024,
|
|
6378
6766
|
// 50KB
|
|
6379
6767
|
maxExecutionsPerMinute: 60,
|
|
6380
|
-
maxResultSize:
|
|
6381
|
-
//
|
|
6768
|
+
maxResultSize: 100 * 1024,
|
|
6769
|
+
// 100KB — context window protection (configurable via CODE_MODE_MAX_RESULT_SIZE)
|
|
6382
6770
|
blockedPatterns: [
|
|
6383
6771
|
/\brequire\s*\(/,
|
|
6384
6772
|
// No require()
|
|
@@ -6493,9 +6881,12 @@ var CodeModeSecurityManager = class {
|
|
|
6493
6881
|
const errors = [];
|
|
6494
6882
|
try {
|
|
6495
6883
|
const serialized = JSON.stringify(result);
|
|
6496
|
-
|
|
6884
|
+
const actualBytes = Buffer.byteLength(serialized, "utf-8");
|
|
6885
|
+
if (actualBytes > this.config.maxResultSize) {
|
|
6886
|
+
const actualKb = Math.ceil(actualBytes / 1024);
|
|
6887
|
+
const limitKb = Math.ceil(this.config.maxResultSize / 1024);
|
|
6497
6888
|
errors.push(
|
|
6498
|
-
`Result exceeds maximum size of ${String(
|
|
6889
|
+
`Result exceeds maximum size of ${String(limitKb)} KB (${String(actualKb)} KB returned). Extract specific fields or aggregate data before returning. Example: instead of \`return await mj.github.getKanbanBoard(5)\`, use \`const b = await mj.github.getKanbanBoard(5); return { columns: b.columns?.length ?? 0, totalItems: b.totalItems }\``
|
|
6499
6890
|
);
|
|
6500
6891
|
}
|
|
6501
6892
|
} catch (error) {
|
|
@@ -6871,7 +7262,12 @@ var ExecuteCodeSchemaMcp = z.object({
|
|
|
6871
7262
|
var securityManager = null;
|
|
6872
7263
|
var sandboxPool = null;
|
|
6873
7264
|
function getSecurityManager() {
|
|
6874
|
-
|
|
7265
|
+
if (!securityManager) {
|
|
7266
|
+
const envMaxSize = process.env["CODE_MODE_MAX_RESULT_SIZE"];
|
|
7267
|
+
const parsedMaxSize = envMaxSize && /^\d+$/.test(envMaxSize) ? parseInt(envMaxSize, 10) : void 0;
|
|
7268
|
+
const overrides = parsedMaxSize !== void 0 && Number.isFinite(parsedMaxSize) && Number.isInteger(parsedMaxSize) && parsedMaxSize > 0 ? { maxResultSize: parsedMaxSize } : void 0;
|
|
7269
|
+
securityManager = new CodeModeSecurityManager(overrides);
|
|
7270
|
+
}
|
|
6875
7271
|
return securityManager;
|
|
6876
7272
|
}
|
|
6877
7273
|
function getSandboxPool() {
|
|
@@ -7343,6 +7739,8 @@ var TOOL_GROUPS = {
|
|
|
7343
7739
|
"get_github_context",
|
|
7344
7740
|
"get_kanban_board",
|
|
7345
7741
|
"move_kanban_item",
|
|
7742
|
+
"add_kanban_item",
|
|
7743
|
+
"delete_kanban_item",
|
|
7346
7744
|
"create_github_issue_with_entry",
|
|
7347
7745
|
"close_github_issue_with_entry",
|
|
7348
7746
|
"get_github_milestones",
|