@stackmemoryai/stackmemory 1.10.4 → 1.12.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 +104 -23
- package/dist/src/cli/claude-sm.js +266 -84
- package/dist/src/cli/codex-sm.js +185 -33
- package/dist/src/cli/commands/bench.js +209 -2
- package/dist/src/cli/commands/cache.js +126 -0
- package/dist/src/cli/commands/daemon.js +41 -0
- package/dist/src/cli/commands/handoff.js +40 -9
- package/dist/src/cli/commands/onboard.js +70 -3
- package/dist/src/cli/commands/optimize.js +117 -0
- package/dist/src/cli/commands/orchestrate.js +230 -5
- package/dist/src/cli/commands/orchestrator.js +312 -24
- package/dist/src/cli/commands/pack.js +322 -0
- package/dist/src/cli/commands/search.js +40 -1
- package/dist/src/cli/commands/setup.js +177 -7
- package/dist/src/cli/commands/skills.js +10 -1
- package/dist/src/cli/commands/state.js +265 -0
- package/dist/src/cli/commands/wiki.js +33 -0
- package/dist/src/cli/gemini-sm.js +19 -29
- package/dist/src/cli/index.js +90 -29
- package/dist/src/cli/opencode-sm.js +38 -21
- package/dist/src/cli/utils/determinism-watcher.js +66 -0
- package/dist/src/cli/utils/real-cli-bin.js +44 -0
- package/dist/src/core/cache/content-cache.js +238 -0
- package/dist/src/core/cache/index.js +11 -0
- package/dist/src/core/cache/token-estimator.js +16 -0
- package/dist/src/core/context/frame-database.js +38 -30
- package/dist/src/core/cross-search/cross-project-search.js +269 -0
- package/dist/src/core/{merge → cross-search}/index.js +6 -4
- package/dist/src/core/database/sqlite-adapter.js +0 -83
- package/dist/src/core/extensions/provider-adapter.js +5 -0
- package/dist/src/core/models/model-router.js +22 -2
- package/dist/src/core/monitoring/logger.js +2 -1
- package/dist/src/core/optimization/trace-optimizer.js +413 -0
- package/dist/src/core/provenance/confidence-scorer.js +128 -0
- package/dist/src/core/provenance/index.js +40 -0
- package/dist/src/core/provenance/provenance-store.js +194 -0
- package/dist/src/core/provenance/types.js +82 -0
- package/dist/src/core/session/project-handoff.js +64 -0
- package/dist/src/core/session/session-manager.js +28 -0
- package/dist/src/core/shared-state/canonical-store.js +564 -0
- package/dist/src/core/skill-packs/index.js +18 -0
- package/dist/src/core/skill-packs/parser.js +42 -0
- package/dist/src/core/skill-packs/registry.js +224 -0
- package/dist/src/core/skill-packs/types.js +66 -0
- package/dist/src/core/trace/trace-event-store.js +282 -0
- package/dist/src/core/trace/trace-event.js +4 -0
- package/dist/src/core/wiki/wiki-compiler.js +219 -0
- package/dist/src/daemon/daemon-config.js +7 -0
- package/dist/src/daemon/services/github-service.js +126 -0
- package/dist/src/daemon/unified-daemon.js +30 -0
- package/dist/src/features/sweep/pty-wrapper.js +13 -5
- package/dist/src/hooks/schemas.js +2 -0
- package/dist/src/integrations/claude-code/subagent-client.js +89 -0
- package/dist/src/integrations/github/pr-state.js +158 -0
- package/dist/src/integrations/linear/client.js +4 -1
- package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +188 -0
- package/dist/src/integrations/mcp/handlers/index.js +40 -59
- package/dist/src/integrations/mcp/server.js +425 -311
- package/dist/src/integrations/mcp/tool-alias-registry.js +370 -0
- package/dist/src/integrations/mcp/tool-definitions.js +98 -229
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +3 -40
- package/dist/src/integrations/ralph/learning/pattern-learner.js +1 -20
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -2
- package/dist/src/mcp/stackmemory-mcp-server.js +315 -0
- package/dist/src/orchestrators/multimodal/determinism.js +243 -0
- package/dist/src/orchestrators/multimodal/harness.js +147 -77
- package/dist/src/orchestrators/multimodal/providers.js +44 -3
- package/dist/src/utils/hook-installer.js +8 -8
- package/package.json +10 -1
- package/packs/coding/python-fastapi/instructions.md +60 -0
- package/packs/coding/python-fastapi/pack.yaml +28 -0
- package/packs/coding/typescript-react/instructions.md +47 -0
- package/packs/coding/typescript-react/pack.yaml +28 -0
- package/packs/core/commands/capture.md +32 -0
- package/packs/core/commands/learn.md +73 -0
- package/packs/core/commands/next.md +36 -0
- package/packs/core/commands/restart.md +58 -0
- package/packs/core/commands/restore.md +29 -0
- package/packs/core/commands/start.md +57 -0
- package/packs/core/commands/stop.md +65 -0
- package/packs/core/commands/summary.md +40 -0
- package/packs/core/manifest.json +24 -0
- package/packs/ops/decision-recovery/instructions.md +65 -0
- package/packs/ops/decision-recovery/pack.yaml +89 -0
- package/templates/claude-hooks/doc-ingest.js +76 -0
- package/dist/src/cli/commands/team.js +0 -168
- package/dist/src/core/context/shared-context-layer.js +0 -620
- package/dist/src/core/context/stack-merge-resolver.js +0 -748
- package/dist/src/core/merge/conflict-detector.js +0 -430
- package/dist/src/core/merge/resolution-engine.js +0 -557
- package/dist/src/core/merge/stack-diff.js +0 -531
- package/dist/src/core/merge/unified-merge-resolver.js +0 -302
- package/dist/src/integrations/mcp/handlers/cord-handlers.js +0 -397
- package/dist/src/integrations/mcp/handlers/team-handlers.js +0 -211
- /package/dist/src/core/{merge → cache}/types.js +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import { execFileSync } from "child_process";
|
|
6
|
+
import {
|
|
7
|
+
canonicalStateStore
|
|
8
|
+
} from "../../core/shared-state/canonical-store.js";
|
|
9
|
+
import { projectIdFromIdentifier } from "../../core/shared-state/canonical-store.js";
|
|
10
|
+
function runGit(args, cwd) {
|
|
11
|
+
return execFileSync("git", args, {
|
|
12
|
+
cwd,
|
|
13
|
+
encoding: "utf8",
|
|
14
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
15
|
+
}).trim();
|
|
16
|
+
}
|
|
17
|
+
function runGh(args, cwd) {
|
|
18
|
+
return execFileSync("gh", args, {
|
|
19
|
+
cwd,
|
|
20
|
+
encoding: "utf8",
|
|
21
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
22
|
+
}).trim();
|
|
23
|
+
}
|
|
24
|
+
function normalizeRemoteToRepo(remote) {
|
|
25
|
+
const cleaned = remote.replace(/\.git$/, "").trim();
|
|
26
|
+
if (cleaned.startsWith("git@github.com:")) {
|
|
27
|
+
return cleaned.replace("git@github.com:", "");
|
|
28
|
+
}
|
|
29
|
+
if (cleaned.startsWith("https://github.com/")) {
|
|
30
|
+
return cleaned.replace("https://github.com/", "");
|
|
31
|
+
}
|
|
32
|
+
if (cleaned.startsWith("http://github.com/")) {
|
|
33
|
+
return cleaned.replace("http://github.com/", "");
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Unsupported GitHub remote: ${remote}`);
|
|
36
|
+
}
|
|
37
|
+
function summarizeStatusCheckRollup(rollup) {
|
|
38
|
+
if (!rollup || rollup.length === 0) {
|
|
39
|
+
return void 0;
|
|
40
|
+
}
|
|
41
|
+
const states = rollup.map((item) => item.conclusion || item.status || item.state).filter(Boolean);
|
|
42
|
+
if (states.length === 0) {
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
if (states.every((state) => state === "SUCCESS")) {
|
|
46
|
+
return "SUCCESS";
|
|
47
|
+
}
|
|
48
|
+
if (states.some((state) => state === "FAILURE" || state === "ERROR")) {
|
|
49
|
+
return "FAILURE";
|
|
50
|
+
}
|
|
51
|
+
if (states.some(
|
|
52
|
+
(state) => state === "PENDING" || state === "IN_PROGRESS" || state === "EXPECTED"
|
|
53
|
+
)) {
|
|
54
|
+
return "PENDING";
|
|
55
|
+
}
|
|
56
|
+
return states[0];
|
|
57
|
+
}
|
|
58
|
+
function getCurrentRepoGitHubInfo(cwd = process.cwd()) {
|
|
59
|
+
try {
|
|
60
|
+
const projectPath = runGit(["rev-parse", "--show-toplevel"], cwd);
|
|
61
|
+
const branch = runGit(["rev-parse", "--abbrev-ref", "HEAD"], projectPath);
|
|
62
|
+
const remote = runGit(
|
|
63
|
+
["config", "--get", "remote.origin.url"],
|
|
64
|
+
projectPath
|
|
65
|
+
);
|
|
66
|
+
const repo = normalizeRemoteToRepo(remote);
|
|
67
|
+
return {
|
|
68
|
+
repo,
|
|
69
|
+
branch,
|
|
70
|
+
projectPath,
|
|
71
|
+
projectId: projectIdFromIdentifier(remote)
|
|
72
|
+
};
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function refreshCurrentRepoPullRequestState(cwd = process.cwd()) {
|
|
78
|
+
const info = getCurrentRepoGitHubInfo(cwd);
|
|
79
|
+
if (!info) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const output = runGh(
|
|
84
|
+
[
|
|
85
|
+
"pr",
|
|
86
|
+
"view",
|
|
87
|
+
"--repo",
|
|
88
|
+
info.repo,
|
|
89
|
+
"--json",
|
|
90
|
+
[
|
|
91
|
+
"number",
|
|
92
|
+
"title",
|
|
93
|
+
"state",
|
|
94
|
+
"isDraft",
|
|
95
|
+
"url",
|
|
96
|
+
"baseRefName",
|
|
97
|
+
"headRefName",
|
|
98
|
+
"headRefOid",
|
|
99
|
+
"mergedAt",
|
|
100
|
+
"updatedAt",
|
|
101
|
+
"reviewDecision",
|
|
102
|
+
"statusCheckRollup"
|
|
103
|
+
].join(",")
|
|
104
|
+
],
|
|
105
|
+
info.projectPath
|
|
106
|
+
);
|
|
107
|
+
const parsed = JSON.parse(output);
|
|
108
|
+
const projection = {
|
|
109
|
+
repo: info.repo,
|
|
110
|
+
branch: info.branch,
|
|
111
|
+
projectId: info.projectId,
|
|
112
|
+
projectPath: info.projectPath,
|
|
113
|
+
prNumber: parsed.number,
|
|
114
|
+
title: parsed.title,
|
|
115
|
+
state: parsed.mergedAt && parsed.state === "MERGED" ? "MERGED" : parsed.state,
|
|
116
|
+
isDraft: parsed.isDraft,
|
|
117
|
+
url: parsed.url,
|
|
118
|
+
baseRefName: parsed.baseRefName,
|
|
119
|
+
headRefName: parsed.headRefName,
|
|
120
|
+
headRefOid: parsed.headRefOid,
|
|
121
|
+
mergedAt: parsed.mergedAt || void 0,
|
|
122
|
+
updatedAt: parsed.updatedAt,
|
|
123
|
+
reviewDecision: parsed.reviewDecision || void 0,
|
|
124
|
+
statusCheckRollup: summarizeStatusCheckRollup(parsed.statusCheckRollup),
|
|
125
|
+
lastSyncedAt: Date.now()
|
|
126
|
+
};
|
|
127
|
+
await canonicalStateStore.saveGitHubPullRequest(projection);
|
|
128
|
+
if (projection.state === "MERGED" || projection.state === "CLOSED") {
|
|
129
|
+
await canonicalStateStore.releaseClaims({
|
|
130
|
+
projectId: info.projectId,
|
|
131
|
+
projectPath: info.projectPath,
|
|
132
|
+
branch: info.branch,
|
|
133
|
+
reason: `github_pr_${projection.state.toLowerCase()}`
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
await canonicalStateStore.appendEvent({
|
|
137
|
+
type: "github_pr_refreshed",
|
|
138
|
+
tool: "stackmemory",
|
|
139
|
+
projectId: info.projectId,
|
|
140
|
+
projectPath: info.projectPath,
|
|
141
|
+
branch: info.branch,
|
|
142
|
+
payload: {
|
|
143
|
+
repo: info.repo,
|
|
144
|
+
prNumber: projection.prNumber,
|
|
145
|
+
state: projection.state,
|
|
146
|
+
reviewDecision: projection.reviewDecision,
|
|
147
|
+
statusCheckRollup: projection.statusCheckRollup
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
return projection;
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export {
|
|
156
|
+
getCurrentRepoGitHubInfo,
|
|
157
|
+
refreshCurrentRepoPullRequestState
|
|
158
|
+
};
|
|
@@ -496,7 +496,10 @@ class LinearClient {
|
|
|
496
496
|
filter: Object.keys(filter).length > 0 ? filter : void 0,
|
|
497
497
|
first: options?.limit || 50
|
|
498
498
|
});
|
|
499
|
-
return result.issues.nodes
|
|
499
|
+
return result.issues.nodes.map((issue) => ({
|
|
500
|
+
...issue,
|
|
501
|
+
labels: Array.isArray(issue.labels) ? issue.labels : issue.labels?.nodes || []
|
|
502
|
+
}));
|
|
500
503
|
}
|
|
501
504
|
/**
|
|
502
505
|
* Assign an issue to a user
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import {
|
|
6
|
+
CrossProjectSearch
|
|
7
|
+
} from "../../../core/cross-search/cross-project-search.js";
|
|
8
|
+
import { logger } from "../../../core/monitoring/logger.js";
|
|
9
|
+
class CrossSearchHandlers {
|
|
10
|
+
crossSearch;
|
|
11
|
+
constructor(deps) {
|
|
12
|
+
this.crossSearch = deps.crossSearch || new CrossProjectSearch();
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* sm_cross_search: Search across all registered project databases.
|
|
16
|
+
*/
|
|
17
|
+
async handleCrossSearch(args) {
|
|
18
|
+
try {
|
|
19
|
+
const { query, limit = 20, exclude_current = false } = args;
|
|
20
|
+
if (!query) {
|
|
21
|
+
throw new Error("query is required");
|
|
22
|
+
}
|
|
23
|
+
const projects = this.crossSearch.listProjects();
|
|
24
|
+
if (projects.length === 0) {
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
type: "text",
|
|
29
|
+
text: "No projects registered. Use sm_cross_discover to scan for project databases, or sm_cross_register to add one manually."
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const excludeProject = exclude_current ? this.getCurrentProjectName() : void 0;
|
|
35
|
+
const start = Date.now();
|
|
36
|
+
const results = await this.crossSearch.search({
|
|
37
|
+
query,
|
|
38
|
+
limit,
|
|
39
|
+
excludeProject
|
|
40
|
+
});
|
|
41
|
+
const elapsed = Date.now() - start;
|
|
42
|
+
if (results.length === 0) {
|
|
43
|
+
return {
|
|
44
|
+
content: [
|
|
45
|
+
{
|
|
46
|
+
type: "text",
|
|
47
|
+
text: `No results found for "${query}" across ${projects.length} project databases (${elapsed}ms).`
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const text = this.formatResults(results, query, projects.length, elapsed);
|
|
53
|
+
return {
|
|
54
|
+
content: [{ type: "text", text }],
|
|
55
|
+
metadata: {
|
|
56
|
+
results: results.map((r) => ({
|
|
57
|
+
project: r.projectName,
|
|
58
|
+
frameId: r.frameId,
|
|
59
|
+
name: r.name,
|
|
60
|
+
score: r.score
|
|
61
|
+
})),
|
|
62
|
+
total: results.length,
|
|
63
|
+
projectsSearched: projects.length,
|
|
64
|
+
elapsedMs: elapsed
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
} catch (error) {
|
|
68
|
+
logger.error(
|
|
69
|
+
"Cross-project search failed",
|
|
70
|
+
error instanceof Error ? error : new Error(String(error))
|
|
71
|
+
);
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* sm_cross_discover: Auto-discover project databases.
|
|
77
|
+
*/
|
|
78
|
+
async handleCrossDiscover(args) {
|
|
79
|
+
try {
|
|
80
|
+
const paths = args.paths;
|
|
81
|
+
const discovered = this.crossSearch.discoverProjects(paths);
|
|
82
|
+
const all = this.crossSearch.listProjects();
|
|
83
|
+
return {
|
|
84
|
+
content: [
|
|
85
|
+
{
|
|
86
|
+
type: "text",
|
|
87
|
+
text: `Discovered ${discovered.length} project database(s).
|
|
88
|
+
Total registered: ${all.length}
|
|
89
|
+
|
|
90
|
+
` + all.map((p) => ` ${p.name}: ${p.path}
|
|
91
|
+
db: ${p.dbPath}`).join("\n")
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
metadata: { discovered: discovered.length, total: all.length }
|
|
95
|
+
};
|
|
96
|
+
} catch (error) {
|
|
97
|
+
logger.error(
|
|
98
|
+
"Cross-project discover failed",
|
|
99
|
+
error instanceof Error ? error : new Error(String(error))
|
|
100
|
+
);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* sm_cross_register: Register a project database manually.
|
|
106
|
+
*/
|
|
107
|
+
async handleCrossRegister(args) {
|
|
108
|
+
try {
|
|
109
|
+
const { name, path, db_path } = args;
|
|
110
|
+
if (!name || !path || !db_path) {
|
|
111
|
+
throw new Error("name, path, and db_path are required");
|
|
112
|
+
}
|
|
113
|
+
this.crossSearch.registerProject({
|
|
114
|
+
name,
|
|
115
|
+
path,
|
|
116
|
+
dbPath: db_path,
|
|
117
|
+
lastAccessed: Date.now()
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
content: [
|
|
121
|
+
{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: `Registered project "${name}" at ${path} (db: ${db_path})`
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
};
|
|
127
|
+
} catch (error) {
|
|
128
|
+
logger.error(
|
|
129
|
+
"Cross-project register failed",
|
|
130
|
+
error instanceof Error ? error : new Error(String(error))
|
|
131
|
+
);
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* sm_cross_list: List all registered project databases.
|
|
137
|
+
*/
|
|
138
|
+
async handleCrossList() {
|
|
139
|
+
try {
|
|
140
|
+
const projects = this.crossSearch.listProjects();
|
|
141
|
+
if (projects.length === 0) {
|
|
142
|
+
return {
|
|
143
|
+
content: [
|
|
144
|
+
{
|
|
145
|
+
type: "text",
|
|
146
|
+
text: "No projects registered. Use sm_cross_discover to scan for project databases."
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
const text = `Registered projects (${projects.length}):
|
|
152
|
+
|
|
153
|
+
` + projects.map(
|
|
154
|
+
(p) => ` ${p.name}
|
|
155
|
+
path: ${p.path}
|
|
156
|
+
db: ${p.dbPath}
|
|
157
|
+
last: ${new Date(p.lastAccessed).toLocaleDateString()}`
|
|
158
|
+
).join("\n");
|
|
159
|
+
return {
|
|
160
|
+
content: [{ type: "text", text }],
|
|
161
|
+
metadata: { projects }
|
|
162
|
+
};
|
|
163
|
+
} catch (error) {
|
|
164
|
+
logger.error(
|
|
165
|
+
"Cross-project list failed",
|
|
166
|
+
error instanceof Error ? error : new Error(String(error))
|
|
167
|
+
);
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
formatResults(results, query, projectCount, elapsed) {
|
|
172
|
+
const header = `Cross-project search: ${results.length} results for "${query}" across ${projectCount} databases (${elapsed}ms):
|
|
173
|
+
|
|
174
|
+
`;
|
|
175
|
+
const body = results.map(
|
|
176
|
+
(r) => `[${r.projectName}] ${r.name} (${r.type}, score: ${r.score.toFixed(3)})` + (r.digestText ? `
|
|
177
|
+
${r.digestText.slice(0, 120)}` : "")
|
|
178
|
+
).join("\n");
|
|
179
|
+
return header + body;
|
|
180
|
+
}
|
|
181
|
+
getCurrentProjectName() {
|
|
182
|
+
const cwd = process.cwd();
|
|
183
|
+
return cwd.split("/").pop();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
export {
|
|
187
|
+
CrossSearchHandlers
|
|
188
|
+
};
|
|
@@ -18,11 +18,12 @@ import {
|
|
|
18
18
|
import {
|
|
19
19
|
ProviderHandlers
|
|
20
20
|
} from "./provider-handlers.js";
|
|
21
|
-
import { TeamHandlers } from "./team-handlers.js";
|
|
22
|
-
import { CordHandlers } from "./cord-handlers.js";
|
|
23
21
|
import {
|
|
24
22
|
ProvenantHandlers
|
|
25
23
|
} from "./provenant-handlers.js";
|
|
24
|
+
import {
|
|
25
|
+
CrossSearchHandlers
|
|
26
|
+
} from "./cross-search-handlers.js";
|
|
26
27
|
import {
|
|
27
28
|
ContextHandlers as ContextHandlers2
|
|
28
29
|
} from "./context-handlers.js";
|
|
@@ -32,18 +33,19 @@ import {
|
|
|
32
33
|
} from "./linear-handlers.js";
|
|
33
34
|
import { TraceHandlers as TraceHandlers2 } from "./trace-handlers.js";
|
|
34
35
|
import { ProviderHandlers as ProviderHandlers2 } from "./provider-handlers.js";
|
|
35
|
-
import { TeamHandlers as TeamHandlers2 } from "./team-handlers.js";
|
|
36
|
-
import { CordHandlers as CordHandlers2 } from "./cord-handlers.js";
|
|
37
36
|
import { ProvenantHandlers as ProvenantHandlers2 } from "./provenant-handlers.js";
|
|
37
|
+
import { CrossSearchHandlers as CrossSearchHandlers2 } from "./cross-search-handlers.js";
|
|
38
|
+
import {
|
|
39
|
+
resolveToolAlias
|
|
40
|
+
} from "../tool-alias-registry.js";
|
|
38
41
|
class MCPHandlerFactory {
|
|
39
42
|
contextHandlers;
|
|
40
43
|
taskHandlers;
|
|
41
44
|
linearHandlers;
|
|
42
45
|
traceHandlers;
|
|
43
46
|
providerHandlers;
|
|
44
|
-
teamHandlers;
|
|
45
|
-
cordHandlers;
|
|
46
47
|
provenantHandlers;
|
|
48
|
+
crossSearchHandlers;
|
|
47
49
|
constructor(deps) {
|
|
48
50
|
this.contextHandlers = new ContextHandlers2({
|
|
49
51
|
frameManager: deps.frameManager
|
|
@@ -62,27 +64,20 @@ class MCPHandlerFactory {
|
|
|
62
64
|
browserMCP: deps.browserMCP
|
|
63
65
|
});
|
|
64
66
|
this.providerHandlers = new ProviderHandlers2();
|
|
65
|
-
if (deps.dbAdapter) {
|
|
66
|
-
this.teamHandlers = new TeamHandlers2({
|
|
67
|
-
frameManager: deps.frameManager,
|
|
68
|
-
dbAdapter: deps.dbAdapter
|
|
69
|
-
});
|
|
70
|
-
this.cordHandlers = new CordHandlers2({
|
|
71
|
-
frameManager: deps.frameManager,
|
|
72
|
-
dbAdapter: deps.dbAdapter
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
67
|
if (deps.projectDir) {
|
|
76
68
|
this.provenantHandlers = new ProvenantHandlers2({
|
|
77
69
|
projectDir: deps.projectDir
|
|
78
70
|
});
|
|
79
71
|
}
|
|
72
|
+
this.crossSearchHandlers = new CrossSearchHandlers2({});
|
|
80
73
|
}
|
|
81
74
|
/**
|
|
82
|
-
* Get handler for a specific tool
|
|
75
|
+
* Get handler for a specific tool.
|
|
76
|
+
* Resolves tool name aliases before lookup.
|
|
83
77
|
*/
|
|
84
78
|
getHandler(toolName) {
|
|
85
|
-
|
|
79
|
+
const { canonicalName } = resolveToolAlias(toolName);
|
|
80
|
+
switch (canonicalName) {
|
|
86
81
|
// Context handlers
|
|
87
82
|
case "get_context":
|
|
88
83
|
return this.contextHandlers.handleGetContext.bind(this.contextHandlers);
|
|
@@ -150,32 +145,6 @@ class MCPHandlerFactory {
|
|
|
150
145
|
return this.providerHandlers.handleBatchCheck.bind(
|
|
151
146
|
this.providerHandlers
|
|
152
147
|
);
|
|
153
|
-
// Team handlers
|
|
154
|
-
case "team_context_get":
|
|
155
|
-
if (!this.teamHandlers) throw new Error("Team tools require dbAdapter");
|
|
156
|
-
return this.teamHandlers.handleTeamContextGet.bind(this.teamHandlers);
|
|
157
|
-
case "team_context_share":
|
|
158
|
-
if (!this.teamHandlers) throw new Error("Team tools require dbAdapter");
|
|
159
|
-
return this.teamHandlers.handleTeamContextShare.bind(this.teamHandlers);
|
|
160
|
-
case "team_search":
|
|
161
|
-
if (!this.teamHandlers) throw new Error("Team tools require dbAdapter");
|
|
162
|
-
return this.teamHandlers.handleTeamSearch.bind(this.teamHandlers);
|
|
163
|
-
// Cord orchestration handlers
|
|
164
|
-
case "cord_spawn":
|
|
165
|
-
if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
|
|
166
|
-
return this.cordHandlers.handleCordSpawn.bind(this.cordHandlers);
|
|
167
|
-
case "cord_fork":
|
|
168
|
-
if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
|
|
169
|
-
return this.cordHandlers.handleCordFork.bind(this.cordHandlers);
|
|
170
|
-
case "cord_complete":
|
|
171
|
-
if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
|
|
172
|
-
return this.cordHandlers.handleCordComplete.bind(this.cordHandlers);
|
|
173
|
-
case "cord_ask":
|
|
174
|
-
if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
|
|
175
|
-
return this.cordHandlers.handleCordAsk.bind(this.cordHandlers);
|
|
176
|
-
case "cord_tree":
|
|
177
|
-
if (!this.cordHandlers) throw new Error("Cord tools require dbAdapter");
|
|
178
|
-
return this.cordHandlers.handleCordTree.bind(this.cordHandlers);
|
|
179
148
|
// Provenant decision graph handlers
|
|
180
149
|
case "provenant_search":
|
|
181
150
|
if (!this.provenantHandlers)
|
|
@@ -201,6 +170,23 @@ class MCPHandlerFactory {
|
|
|
201
170
|
return this.provenantHandlers.handleResolve.bind(
|
|
202
171
|
this.provenantHandlers
|
|
203
172
|
);
|
|
173
|
+
// Cross-project search handlers
|
|
174
|
+
case "sm_cross_search":
|
|
175
|
+
return this.crossSearchHandlers.handleCrossSearch.bind(
|
|
176
|
+
this.crossSearchHandlers
|
|
177
|
+
);
|
|
178
|
+
case "sm_cross_discover":
|
|
179
|
+
return this.crossSearchHandlers.handleCrossDiscover.bind(
|
|
180
|
+
this.crossSearchHandlers
|
|
181
|
+
);
|
|
182
|
+
case "sm_cross_register":
|
|
183
|
+
return this.crossSearchHandlers.handleCrossRegister.bind(
|
|
184
|
+
this.crossSearchHandlers
|
|
185
|
+
);
|
|
186
|
+
case "sm_cross_list":
|
|
187
|
+
return this.crossSearchHandlers.handleCrossList.bind(
|
|
188
|
+
this.crossSearchHandlers
|
|
189
|
+
);
|
|
204
190
|
default:
|
|
205
191
|
throw new Error(`Unknown tool: ${toolName}`);
|
|
206
192
|
}
|
|
@@ -237,40 +223,35 @@ class MCPHandlerFactory {
|
|
|
237
223
|
"delegate_to_model",
|
|
238
224
|
"batch_submit",
|
|
239
225
|
"batch_check",
|
|
240
|
-
// Team tools
|
|
241
|
-
"team_context_get",
|
|
242
|
-
"team_context_share",
|
|
243
|
-
"team_search",
|
|
244
|
-
// Cord orchestration tools
|
|
245
|
-
"cord_spawn",
|
|
246
|
-
"cord_fork",
|
|
247
|
-
"cord_complete",
|
|
248
|
-
"cord_ask",
|
|
249
|
-
"cord_tree",
|
|
250
226
|
// Provenant decision graph tools
|
|
251
227
|
"provenant_search",
|
|
252
228
|
"provenant_log",
|
|
253
229
|
"provenant_status",
|
|
254
230
|
"provenant_contradictions",
|
|
255
|
-
"provenant_resolve"
|
|
231
|
+
"provenant_resolve",
|
|
232
|
+
// Cross-project search tools
|
|
233
|
+
"sm_cross_search",
|
|
234
|
+
"sm_cross_discover",
|
|
235
|
+
"sm_cross_register",
|
|
236
|
+
"sm_cross_list"
|
|
256
237
|
];
|
|
257
238
|
}
|
|
258
239
|
/**
|
|
259
|
-
* Check if a tool exists
|
|
240
|
+
* Check if a tool exists (resolves aliases)
|
|
260
241
|
*/
|
|
261
242
|
hasHandler(toolName) {
|
|
262
|
-
|
|
243
|
+
const { canonicalName } = resolveToolAlias(toolName);
|
|
244
|
+
return this.getAvailableTools().includes(canonicalName);
|
|
263
245
|
}
|
|
264
246
|
}
|
|
265
247
|
export {
|
|
266
248
|
ContextHandlers,
|
|
267
|
-
|
|
249
|
+
CrossSearchHandlers,
|
|
268
250
|
DiscoveryHandlers,
|
|
269
251
|
LinearHandlers,
|
|
270
252
|
MCPHandlerFactory,
|
|
271
253
|
ProvenantHandlers,
|
|
272
254
|
ProviderHandlers,
|
|
273
255
|
TaskHandlers,
|
|
274
|
-
TeamHandlers,
|
|
275
256
|
TraceHandlers
|
|
276
257
|
};
|