@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.
@@ -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 task status
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
- try {
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
- updateData.status = status;
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.labels = Array.isArray(labels) ? labels : [labels];
92
+ updateData.labelIds = Array.isArray(labels) ? labels : [labels];
95
93
  }
96
- throw new Error(
97
- "Linear issue updates via MCP are not yet implemented. Use `stackmemory linear sync` instead."
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 tasks from Linear
119
+ * Get issues from Linear via GraphQL API
109
120
  */
110
121
  async handleLinearGetTasks(args) {
111
122
  try {
112
- const {
113
- team_id,
114
- assignee_id,
115
- state = "active",
116
- limit = 20,
117
- search
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
- if (team_id) {
128
- filters.teamId = team_id;
129
- }
130
- if (assignee_id) {
131
- filters.assigneeId = assignee_id;
132
- }
133
- if (state) {
134
- filters.state = state;
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.0",
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",