@stackmemoryai/stackmemory 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/cli/commands/symphony-orchestrator.js +676 -0
- package/dist/src/cli/commands/symphony.js +30 -1
- package/dist/src/core/database/sqlite-adapter.js +152 -8
- package/dist/src/integrations/claude-code/subagent-client.js +97 -161
- package/dist/src/integrations/claude-code/task-coordinator.js +69 -21
- package/dist/src/integrations/mcp/handlers/linear-handlers.js +62 -48
- package/package.json +1 -1
|
@@ -2,11 +2,19 @@ import { fileURLToPath as __fileURLToPath } from 'url';
|
|
|
2
2
|
import { dirname as __pathDirname } from 'path';
|
|
3
3
|
const __filename = __fileURLToPath(import.meta.url);
|
|
4
4
|
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import { LinearClient } from "../../linear/client.js";
|
|
5
6
|
import { logger } from "../../../core/monitoring/logger.js";
|
|
6
7
|
class LinearHandlers {
|
|
7
8
|
constructor(deps) {
|
|
8
9
|
this.deps = deps;
|
|
9
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Create an authenticated LinearClient from the auth manager token
|
|
13
|
+
*/
|
|
14
|
+
async getClient() {
|
|
15
|
+
const token = await this.deps.linearAuthManager.getValidToken();
|
|
16
|
+
return new LinearClient({ apiKey: token, useBearer: true });
|
|
17
|
+
}
|
|
10
18
|
/**
|
|
11
19
|
* Sync tasks with Linear
|
|
12
20
|
*/
|
|
@@ -67,7 +75,7 @@ class LinearHandlers {
|
|
|
67
75
|
}
|
|
68
76
|
}
|
|
69
77
|
/**
|
|
70
|
-
* Update Linear
|
|
78
|
+
* Update Linear issue directly via GraphQL API
|
|
71
79
|
*/
|
|
72
80
|
async handleLinearUpdateTask(args) {
|
|
73
81
|
try {
|
|
@@ -75,27 +83,30 @@ class LinearHandlers {
|
|
|
75
83
|
if (!linear_id) {
|
|
76
84
|
throw new Error("Linear ID is required");
|
|
77
85
|
}
|
|
78
|
-
|
|
79
|
-
await this.deps.linearAuthManager.getValidToken();
|
|
80
|
-
} catch {
|
|
81
|
-
throw new Error("Linear authentication required");
|
|
82
|
-
}
|
|
86
|
+
const client = await this.getClient();
|
|
83
87
|
const updateData = {};
|
|
84
|
-
if (status)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (assignee_id) {
|
|
88
|
-
updateData.assigneeId = assignee_id;
|
|
89
|
-
}
|
|
90
|
-
if (priority) {
|
|
91
|
-
updateData.priority = priority;
|
|
92
|
-
}
|
|
88
|
+
if (status) updateData.stateId = status;
|
|
89
|
+
if (assignee_id) updateData.assigneeId = assignee_id;
|
|
90
|
+
if (priority !== void 0) updateData.priority = priority;
|
|
93
91
|
if (labels) {
|
|
94
|
-
updateData.
|
|
92
|
+
updateData.labelIds = Array.isArray(labels) ? labels : [labels];
|
|
95
93
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
const issue = await client.updateIssue(linear_id, updateData);
|
|
95
|
+
return {
|
|
96
|
+
content: [
|
|
97
|
+
{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Updated ${issue.identifier}: ${issue.title}
|
|
100
|
+
Status: ${issue.state.name} | Priority: ${issue.priority}`
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
metadata: {
|
|
104
|
+
id: issue.id,
|
|
105
|
+
identifier: issue.identifier,
|
|
106
|
+
state: issue.state.name,
|
|
107
|
+
url: issue.url
|
|
108
|
+
}
|
|
109
|
+
};
|
|
99
110
|
} catch (error) {
|
|
100
111
|
logger.error(
|
|
101
112
|
"Error updating Linear task",
|
|
@@ -105,40 +116,43 @@ class LinearHandlers {
|
|
|
105
116
|
}
|
|
106
117
|
}
|
|
107
118
|
/**
|
|
108
|
-
* Get
|
|
119
|
+
* Get issues from Linear via GraphQL API
|
|
109
120
|
*/
|
|
110
121
|
async handleLinearGetTasks(args) {
|
|
111
122
|
try {
|
|
112
|
-
const {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
} = args;
|
|
119
|
-
try {
|
|
120
|
-
await this.deps.linearAuthManager.getValidToken();
|
|
121
|
-
} catch {
|
|
122
|
-
throw new Error("Linear authentication required");
|
|
123
|
-
}
|
|
124
|
-
const filters = {
|
|
125
|
-
limit
|
|
123
|
+
const { team_id, assignee_id, state = "active", limit = 20 } = args;
|
|
124
|
+
const client = await this.getClient();
|
|
125
|
+
const stateTypeMap = {
|
|
126
|
+
active: "started",
|
|
127
|
+
closed: "completed",
|
|
128
|
+
all: void 0
|
|
126
129
|
};
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
136
|
-
if (search) {
|
|
137
|
-
filters.search = search;
|
|
138
|
-
}
|
|
139
|
-
throw new Error(
|
|
140
|
-
"Linear issue listing via MCP is not yet implemented. Use `stackmemory linear sync` instead."
|
|
130
|
+
const issues = await client.getIssues({
|
|
131
|
+
teamId: team_id,
|
|
132
|
+
assigneeId: assignee_id,
|
|
133
|
+
stateType: stateTypeMap[state],
|
|
134
|
+
limit
|
|
135
|
+
});
|
|
136
|
+
const issueLines = issues.map(
|
|
137
|
+
(i) => `${i.identifier} [${i.state.name}] ${i.title}${i.assignee ? ` (@${i.assignee.name})` : ""}`
|
|
141
138
|
);
|
|
139
|
+
const text = issues.length > 0 ? `Found ${issues.length} issues:
|
|
140
|
+
${issueLines.join("\n")}` : "No issues found matching filters.";
|
|
141
|
+
return {
|
|
142
|
+
content: [{ type: "text", text }],
|
|
143
|
+
metadata: {
|
|
144
|
+
count: issues.length,
|
|
145
|
+
issues: issues.map((i) => ({
|
|
146
|
+
id: i.id,
|
|
147
|
+
identifier: i.identifier,
|
|
148
|
+
title: i.title,
|
|
149
|
+
state: i.state.name,
|
|
150
|
+
priority: i.priority,
|
|
151
|
+
assignee: i.assignee?.name,
|
|
152
|
+
url: i.url
|
|
153
|
+
}))
|
|
154
|
+
}
|
|
155
|
+
};
|
|
142
156
|
} catch (error) {
|
|
143
157
|
logger.error(
|
|
144
158
|
"Error getting Linear tasks",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackmemoryai/stackmemory",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "Project-scoped memory for AI coding tools. Durable context across sessions with 56 MCP tools, FTS5 search, Claude/Codex/OpenCode wrappers, Linear sync, automatic hooks, and log analysis.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.0.0",
|