@stackmemoryai/stackmemory 1.12.0 → 1.14.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.
Files changed (162) hide show
  1. package/LICENSE +131 -64
  2. package/README.md +3 -1
  3. package/bin/claude-sm +16 -1
  4. package/bin/claude-smd +16 -1
  5. package/bin/codex-smd +16 -1
  6. package/bin/gemini-sm +16 -1
  7. package/bin/hermes-sm +21 -0
  8. package/bin/hermes-smd +21 -0
  9. package/bin/opencode-sm +16 -1
  10. package/dist/src/cli/codex-sm.js +51 -11
  11. package/dist/src/cli/commands/brain.js +206 -0
  12. package/dist/src/cli/commands/company-os.js +184 -0
  13. package/dist/src/cli/commands/context.js +5 -0
  14. package/dist/src/cli/commands/operator.js +127 -0
  15. package/dist/src/cli/commands/orchestrate.js +2 -0
  16. package/dist/src/cli/commands/orchestrator.js +3 -2
  17. package/dist/src/cli/commands/patterns.js +254 -0
  18. package/dist/src/cli/commands/portal.js +161 -0
  19. package/dist/src/cli/commands/scaffold.js +92 -0
  20. package/dist/src/cli/commands/setup.js +1 -4
  21. package/dist/src/cli/commands/sync.js +253 -0
  22. package/dist/src/cli/commands/tasks.js +130 -1
  23. package/dist/src/cli/commands/vision.js +221 -0
  24. package/dist/src/cli/hermes-sm.js +224 -0
  25. package/dist/src/cli/index.js +15 -10
  26. package/dist/src/cli/utils/real-cli-bin.js +72 -0
  27. package/dist/src/core/brain/brain-store.js +187 -0
  28. package/dist/src/core/brain/brain-sync.js +193 -0
  29. package/dist/src/core/brain/index.js +78 -0
  30. package/dist/src/core/brain/types.js +10 -0
  31. package/dist/src/core/cache/token-estimator.js +24 -1
  32. package/dist/src/core/config/feature-flags.js +2 -6
  33. package/dist/src/core/context/frame-database.js +44 -0
  34. package/dist/src/core/context/recursive-context-manager.js +1 -1
  35. package/dist/src/core/context/rehydration.js +2 -1
  36. package/dist/src/core/database/sqlite-adapter.js +14 -1
  37. package/dist/src/core/models/model-router.js +33 -1
  38. package/dist/src/core/models/provider-pricing.js +58 -4
  39. package/dist/src/core/patterns/index.js +22 -0
  40. package/dist/src/core/patterns/pattern-applier.js +39 -0
  41. package/dist/src/core/patterns/pattern-observer.js +157 -0
  42. package/dist/src/core/patterns/pattern-store.js +259 -0
  43. package/dist/src/core/patterns/types.js +19 -0
  44. package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
  45. package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
  46. package/dist/src/core/skill-packs/types.js +14 -1
  47. package/dist/src/core/storage/cloud-sync-manager.js +116 -0
  48. package/dist/src/core/storage/cloud-sync.js +574 -0
  49. package/dist/src/core/storage/two-tier-storage.js +5 -1
  50. package/dist/src/core/tasks/master-tasks-template.js +43 -0
  51. package/dist/src/core/tasks/md-task-parser.js +138 -0
  52. package/dist/src/core/vision/index.js +27 -0
  53. package/dist/src/core/vision/signals.js +79 -0
  54. package/dist/src/core/vision/types.js +22 -0
  55. package/dist/src/core/vision/vision-file.js +146 -0
  56. package/dist/src/core/vision/vision-loop.js +220 -0
  57. package/dist/src/core/wiki/wiki-compiler.js +103 -1
  58. package/dist/src/daemon/daemon-config.js +45 -0
  59. package/dist/src/daemon/services/desire-path-service.js +566 -0
  60. package/dist/src/daemon/services/research-stream-service.js +320 -0
  61. package/dist/src/daemon/services/telemetry-service.js +192 -0
  62. package/dist/src/daemon/unified-daemon.js +28 -1
  63. package/dist/src/features/browser/cli-browser-agent.js +417 -0
  64. package/dist/src/features/browser/stagehand-workflows.js +578 -0
  65. package/dist/src/features/operator/adapter-factory.js +62 -0
  66. package/dist/src/features/operator/browser-adapter.js +109 -0
  67. package/dist/src/features/operator/desktop-adapter.js +125 -0
  68. package/dist/src/features/operator/index.js +39 -0
  69. package/dist/src/features/operator/llm-decision.js +137 -0
  70. package/dist/src/features/operator/operator-logger.js +92 -0
  71. package/dist/src/features/operator/overnight-runner.js +327 -0
  72. package/dist/src/features/operator/screen-adapter.js +91 -0
  73. package/dist/src/features/operator/session-manager.js +127 -0
  74. package/dist/src/features/operator/state-machine.js +227 -0
  75. package/dist/src/features/operator/task-queue.js +81 -0
  76. package/dist/src/features/portal/index.js +26 -0
  77. package/dist/src/features/portal/server.js +240 -0
  78. package/dist/src/features/portal/types.js +14 -0
  79. package/dist/src/features/portal/ui.js +195 -0
  80. package/dist/src/features/tasks/task-aware-context.js +2 -1
  81. package/dist/src/features/tui/simple-monitor.js +0 -23
  82. package/dist/src/features/tui/swarm-monitor.js +8 -66
  83. package/dist/src/{integrations/diffmem/index.js → features/web/client/hooks/use-socket.js} +6 -5
  84. package/dist/src/features/web/client/lib/utils.js +12 -0
  85. package/dist/src/features/web/client/stores/session-store.js +12 -0
  86. package/dist/src/features/web/server/gcp-billing.js +76 -0
  87. package/dist/src/features/web/server/index.js +10 -0
  88. package/dist/src/features/web/server/spend-calculator.js +228 -0
  89. package/dist/src/hooks/schemas.js +4 -1
  90. package/dist/src/integrations/anthropic/client.js +3 -2
  91. package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
  92. package/dist/src/integrations/claude-code/subagent-client.js +218 -11
  93. package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
  94. package/dist/src/integrations/linear/webhook-retry.js +196 -0
  95. package/dist/src/integrations/linear/webhook-server.js +18 -22
  96. package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
  97. package/dist/src/integrations/mcp/handlers/index.js +27 -52
  98. package/dist/src/integrations/mcp/server.js +122 -335
  99. package/dist/src/integrations/mcp/tool-alias-registry.js +0 -73
  100. package/dist/src/integrations/mcp/tool-definitions.js +111 -510
  101. package/dist/src/mcp/stackmemory-mcp-server.js +404 -379
  102. package/dist/src/orchestrators/multimodal/determinism.js +2 -1
  103. package/dist/src/orchestrators/multimodal/harness.js +2 -1
  104. package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
  105. package/dist/src/utils/process-cleanup.js +1 -7
  106. package/docs/README.md +42 -0
  107. package/docs/guides/README_INSTALL.md +208 -0
  108. package/package.json +18 -9
  109. package/scripts/claude-code-wrapper.sh +11 -0
  110. package/scripts/claude-sm-setup.sh +12 -1
  111. package/scripts/codex-wrapper.sh +11 -0
  112. package/scripts/git-hooks/branch-context-manager.sh +11 -0
  113. package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
  114. package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
  115. package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
  116. package/scripts/hooks/cleanup-shell.sh +12 -1
  117. package/scripts/hooks/task-complete.sh +12 -1
  118. package/scripts/install-code-execution-hooks.sh +12 -1
  119. package/scripts/install-sweep-hook.sh +12 -0
  120. package/scripts/install.sh +11 -0
  121. package/scripts/opencode-wrapper.sh +11 -0
  122. package/scripts/portal/cloud-init.yaml +69 -0
  123. package/scripts/portal/setup.sh +69 -0
  124. package/scripts/portal/stackmemory-portal.service +34 -0
  125. package/scripts/setup-claude-integration.sh +12 -1
  126. package/scripts/smoke-init-db.sh +23 -0
  127. package/scripts/stackmemory-daemon.sh +11 -0
  128. package/scripts/verify-dist.cjs +11 -4
  129. package/dist/src/cli/commands/ralph.js +0 -1053
  130. package/dist/src/hooks/diffmem-hooks.js +0 -376
  131. package/dist/src/integrations/diffmem/client.js +0 -208
  132. package/dist/src/integrations/diffmem/config.js +0 -14
  133. package/dist/src/integrations/greptile/client.js +0 -101
  134. package/dist/src/integrations/greptile/config.js +0 -14
  135. package/dist/src/integrations/greptile/index.js +0 -11
  136. package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +0 -188
  137. package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
  138. package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
  139. package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
  140. package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
  141. package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
  142. package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -354
  143. package/dist/src/integrations/ralph/index.js +0 -17
  144. package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -416
  145. package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
  146. package/dist/src/integrations/ralph/loopmax.js +0 -488
  147. package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
  148. package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
  149. package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
  150. package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
  151. package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
  152. package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
  153. package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
  154. package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
  155. package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
  156. package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
  157. package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1005
  158. package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
  159. package/scripts/ralph-loop-implementation.js +0 -404
  160. /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
  161. /package/dist/src/{integrations/greptile → features/operator}/types.js +0 -0
  162. /package/dist/src/{integrations/ralph/types.js → features/web/client/next-env.d.js} +0 -0
@@ -0,0 +1,196 @@
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 Database from "better-sqlite3";
6
+ import { randomUUID } from "crypto";
7
+ import { calculateBackoff } from "../../core/errors/recovery.js";
8
+ import { logger } from "../../core/monitoring/logger.js";
9
+ const DEFAULT_CONFIG = {
10
+ maxAttempts: 5,
11
+ initialDelay: 1e3,
12
+ maxDelay: 3e5,
13
+ backoffFactor: 2,
14
+ workerIntervalMs: 5e3
15
+ };
16
+ class WebhookDeliveryQueue {
17
+ db;
18
+ config;
19
+ workerTimer = null;
20
+ handler = null;
21
+ constructor(dbPath, config) {
22
+ this.config = { ...DEFAULT_CONFIG, ...config };
23
+ this.db = new Database(dbPath);
24
+ this.db.pragma("journal_mode = WAL");
25
+ this.ensureSchema();
26
+ }
27
+ ensureSchema() {
28
+ this.db.exec(`
29
+ CREATE TABLE IF NOT EXISTS webhook_deliveries (
30
+ id TEXT PRIMARY KEY,
31
+ event_type TEXT NOT NULL,
32
+ payload TEXT NOT NULL,
33
+ status TEXT NOT NULL DEFAULT 'pending',
34
+ attempts INTEGER NOT NULL DEFAULT 0,
35
+ max_attempts INTEGER NOT NULL DEFAULT 5,
36
+ next_retry_at INTEGER,
37
+ last_error TEXT,
38
+ created_at INTEGER NOT NULL,
39
+ updated_at INTEGER NOT NULL
40
+ );
41
+ CREATE INDEX IF NOT EXISTS idx_webhook_deliveries_status_retry
42
+ ON webhook_deliveries(status, next_retry_at);
43
+ `);
44
+ }
45
+ /**
46
+ * Set the handler function that processes webhook events.
47
+ */
48
+ setHandler(fn) {
49
+ this.handler = fn;
50
+ }
51
+ /**
52
+ * Enqueue a webhook event for processing.
53
+ */
54
+ enqueue(eventType, payload) {
55
+ const id = randomUUID();
56
+ const now = Date.now();
57
+ this.db.prepare(
58
+ `INSERT INTO webhook_deliveries
59
+ (id, event_type, payload, status, attempts, max_attempts, next_retry_at, created_at, updated_at)
60
+ VALUES (?, ?, ?, 'pending', 0, ?, ?, ?, ?)`
61
+ ).run(
62
+ id,
63
+ eventType,
64
+ JSON.stringify(payload),
65
+ this.config.maxAttempts,
66
+ now,
67
+ now,
68
+ now
69
+ );
70
+ return id;
71
+ }
72
+ /**
73
+ * Process the next eligible delivery. Returns true if a delivery was processed.
74
+ */
75
+ async processNext() {
76
+ if (!this.handler) {
77
+ return false;
78
+ }
79
+ const now = Date.now();
80
+ const delivery = this.db.prepare(
81
+ `UPDATE webhook_deliveries
82
+ SET status = 'processing', updated_at = ?
83
+ WHERE id = (
84
+ SELECT id FROM webhook_deliveries
85
+ WHERE (status = 'pending' OR (status = 'failed' AND next_retry_at <= ?))
86
+ ORDER BY next_retry_at ASC, created_at ASC
87
+ LIMIT 1
88
+ )
89
+ RETURNING *`
90
+ ).get(now, now);
91
+ if (!delivery) {
92
+ return false;
93
+ }
94
+ const attempt = delivery.attempts + 1;
95
+ try {
96
+ const payload = JSON.parse(delivery.payload);
97
+ await this.handler(delivery.event_type, payload);
98
+ this.db.prepare(
99
+ `UPDATE webhook_deliveries
100
+ SET status = 'completed', attempts = ?, last_error = NULL, updated_at = ?
101
+ WHERE id = ?`
102
+ ).run(attempt, Date.now(), delivery.id);
103
+ logger.info(
104
+ `Webhook delivery ${delivery.id} completed on attempt ${attempt}`
105
+ );
106
+ return true;
107
+ } catch (error) {
108
+ const errorMsg = error instanceof Error ? error.message : String(error);
109
+ if (attempt >= delivery.max_attempts) {
110
+ this.db.prepare(
111
+ `UPDATE webhook_deliveries
112
+ SET status = 'dead', attempts = ?, last_error = ?, updated_at = ?
113
+ WHERE id = ?`
114
+ ).run(attempt, errorMsg, Date.now(), delivery.id);
115
+ logger.error(
116
+ `Webhook delivery ${delivery.id} dead after ${attempt} attempts: ${errorMsg}`
117
+ );
118
+ } else {
119
+ const delay = calculateBackoff(
120
+ attempt,
121
+ this.config.initialDelay,
122
+ this.config.maxDelay,
123
+ this.config.backoffFactor
124
+ );
125
+ const nextRetry = Date.now() + delay;
126
+ this.db.prepare(
127
+ `UPDATE webhook_deliveries
128
+ SET status = 'failed', attempts = ?, last_error = ?, next_retry_at = ?, updated_at = ?
129
+ WHERE id = ?`
130
+ ).run(attempt, errorMsg, nextRetry, Date.now(), delivery.id);
131
+ logger.warn(
132
+ `Webhook delivery ${delivery.id} failed (attempt ${attempt}/${delivery.max_attempts}), retry in ${delay}ms`
133
+ );
134
+ }
135
+ return true;
136
+ }
137
+ }
138
+ /**
139
+ * Start the background worker that polls for deliveries.
140
+ */
141
+ startWorker() {
142
+ if (this.workerTimer) return;
143
+ this.workerTimer = setInterval(async () => {
144
+ try {
145
+ while (await this.processNext()) {
146
+ }
147
+ } catch (error) {
148
+ logger.error("Webhook retry worker error", error);
149
+ }
150
+ }, this.config.workerIntervalMs);
151
+ }
152
+ /**
153
+ * Stop the background worker.
154
+ */
155
+ stopWorker() {
156
+ if (this.workerTimer) {
157
+ clearInterval(this.workerTimer);
158
+ this.workerTimer = null;
159
+ }
160
+ }
161
+ /**
162
+ * Get delivery counts by status.
163
+ */
164
+ getStats() {
165
+ const rows = this.db.prepare(
166
+ `SELECT status, COUNT(*) as count FROM webhook_deliveries GROUP BY status`
167
+ ).all();
168
+ const stats = {
169
+ pending: 0,
170
+ processing: 0,
171
+ completed: 0,
172
+ failed: 0,
173
+ dead: 0
174
+ };
175
+ for (const row of rows) {
176
+ stats[row.status] = row.count;
177
+ }
178
+ return stats;
179
+ }
180
+ /**
181
+ * Get a single delivery by ID.
182
+ */
183
+ getDelivery(id) {
184
+ return this.db.prepare(`SELECT * FROM webhook_deliveries WHERE id = ?`).get(id);
185
+ }
186
+ /**
187
+ * Close the database connection and stop the worker.
188
+ */
189
+ close() {
190
+ this.stopWorker();
191
+ this.db.close();
192
+ }
193
+ }
194
+ export {
195
+ WebhookDeliveryQueue
196
+ };
@@ -8,7 +8,10 @@ import crypto from "crypto";
8
8
  import { LinearSyncService } from "./sync-service.js";
9
9
  import { IntegrationError, ErrorCode } from "../../core/errors/index.js";
10
10
  import { logger } from "../../core/monitoring/logger.js";
11
+ import { WebhookDeliveryQueue } from "./webhook-retry.js";
11
12
  import chalk from "chalk";
13
+ import { join } from "path";
14
+ import { homedir } from "os";
12
15
  function _getEnv(key, defaultValue) {
13
16
  const value = process.env[key];
14
17
  if (value === void 0) {
@@ -29,21 +32,28 @@ class LinearWebhookServer {
29
32
  // Using singleton logger from monitoring
30
33
  syncService;
31
34
  config;
32
- eventQueue = [];
33
- isProcessing = false;
35
+ deliveryQueue;
34
36
  constructor(config) {
35
37
  this.app = express();
36
38
  this.syncService = new LinearSyncService();
39
+ const dbPath = config?.dbPath || join(homedir(), ".stackmemory", "webhook-deliveries.db");
37
40
  this.config = {
38
41
  port: config?.port || parseInt(process.env["WEBHOOK_PORT"] || "3456"),
39
42
  host: config?.host || process.env["WEBHOOK_HOST"] || "localhost",
40
43
  webhookSecret: config?.webhookSecret || process.env["LINEAR_WEBHOOK_SECRET"],
41
44
  maxPayloadSize: config?.maxPayloadSize || "10mb",
45
+ dbPath,
42
46
  rateLimit: {
43
47
  windowMs: config?.rateLimit?.windowMs || 6e4,
44
48
  max: config?.rateLimit?.max || 100
45
49
  }
46
50
  };
51
+ this.deliveryQueue = new WebhookDeliveryQueue(dbPath);
52
+ this.deliveryQueue.setHandler(
53
+ async (eventType, payload) => {
54
+ await this.handleWebhookEvent(payload);
55
+ }
56
+ );
47
57
  this.setupMiddleware();
48
58
  this.setupRoutes();
49
59
  }
@@ -61,12 +71,12 @@ class LinearWebhookServer {
61
71
  }
62
72
  setupRoutes() {
63
73
  this.app.get("/health", (req, res) => {
74
+ const stats = this.deliveryQueue.getStats();
64
75
  res.json({
65
76
  status: "healthy",
66
77
  service: "linear-webhook",
67
78
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
68
- queue: this.eventQueue.length,
69
- processing: this.isProcessing
79
+ deliveries: stats
70
80
  });
71
81
  });
72
82
  this.app.post("/webhook/linear", async (req, res) => {
@@ -77,11 +87,10 @@ class LinearWebhookServer {
77
87
  }
78
88
  const payload = JSON.parse(req.body.toString());
79
89
  logger.info(`Received webhook: ${payload.type} - ${payload.action}`);
80
- this.eventQueue.push(payload);
81
- this.processQueue();
90
+ const deliveryId = this.deliveryQueue.enqueue(payload.type, payload);
82
91
  return res.status(200).json({
83
92
  status: "accepted",
84
- queued: true
93
+ deliveryId
85
94
  });
86
95
  } catch (error) {
87
96
  logger.error("Webhook processing error:", error);
@@ -104,21 +113,6 @@ class LinearWebhookServer {
104
113
  const hash = crypto.createHmac("sha256", this.config.webhookSecret).update(req.body).digest("hex");
105
114
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(hash));
106
115
  }
107
- async processQueue() {
108
- if (this.isProcessing || this.eventQueue.length === 0) {
109
- return;
110
- }
111
- this.isProcessing = true;
112
- while (this.eventQueue.length > 0) {
113
- const event = this.eventQueue.shift();
114
- try {
115
- await this.handleWebhookEvent(event);
116
- } catch (error) {
117
- logger.error(`Failed to process event: ${event.type}`, error);
118
- }
119
- }
120
- this.isProcessing = false;
121
- }
122
116
  async handleWebhookEvent(payload) {
123
117
  const { type, action, data } = payload;
124
118
  switch (type) {
@@ -166,6 +160,7 @@ class LinearWebhookServer {
166
160
  this.config.port,
167
161
  this.config.host,
168
162
  () => {
163
+ this.deliveryQueue.startWorker();
169
164
  console.log(
170
165
  chalk.green("\u2713") + chalk.bold(" Linear Webhook Server Started")
171
166
  );
@@ -188,6 +183,7 @@ class LinearWebhookServer {
188
183
  });
189
184
  }
190
185
  async stop() {
186
+ this.deliveryQueue.close();
191
187
  return new Promise((resolve) => {
192
188
  if (this.server) {
193
189
  this.server.close(() => {
@@ -0,0 +1,101 @@
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
+ const VALID_SYNC_TABLES = /* @__PURE__ */ new Set([
6
+ "frames",
7
+ "events",
8
+ "anchors",
9
+ "trace_events",
10
+ "entity_states"
11
+ ]);
12
+ class CloudSyncHandlers {
13
+ syncManager;
14
+ constructor(deps) {
15
+ this.syncManager = deps.syncManager;
16
+ }
17
+ ensureManager() {
18
+ if (!this.syncManager) {
19
+ throw new Error(
20
+ "Cloud sync not configured. Run `stackmemory login` to connect to Provenant."
21
+ );
22
+ }
23
+ return this.syncManager;
24
+ }
25
+ async handlePush(args) {
26
+ const manager = this.ensureManager();
27
+ const result = await manager.performPush("manual", args.force);
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: JSON.stringify(
33
+ {
34
+ success: result.success,
35
+ pushed: result.pushed,
36
+ rejected: result.rejected,
37
+ conflicts: result.conflicts,
38
+ error: result.error
39
+ },
40
+ null,
41
+ 2
42
+ )
43
+ }
44
+ ]
45
+ };
46
+ }
47
+ async handlePull(args) {
48
+ const manager = this.ensureManager();
49
+ const tables = args.tables?.filter((t) => VALID_SYNC_TABLES.has(t));
50
+ const result = await manager.performPull("manual", tables);
51
+ return {
52
+ content: [
53
+ {
54
+ type: "text",
55
+ text: JSON.stringify(
56
+ {
57
+ success: result.success,
58
+ pulled: result.pulled,
59
+ applied: result.applied,
60
+ conflicts: result.conflicts,
61
+ error: result.error
62
+ },
63
+ null,
64
+ 2
65
+ )
66
+ }
67
+ ]
68
+ };
69
+ }
70
+ async handleStatus() {
71
+ if (!this.syncManager) {
72
+ return {
73
+ content: [
74
+ {
75
+ type: "text",
76
+ text: JSON.stringify(
77
+ {
78
+ connected: false,
79
+ message: "Cloud sync not configured. Run `stackmemory login` to connect."
80
+ },
81
+ null,
82
+ 2
83
+ )
84
+ }
85
+ ]
86
+ };
87
+ }
88
+ const status = this.syncManager.getStatus();
89
+ return {
90
+ content: [
91
+ {
92
+ type: "text",
93
+ text: JSON.stringify(status, null, 2)
94
+ }
95
+ ]
96
+ };
97
+ }
98
+ }
99
+ export {
100
+ CloudSyncHandlers
101
+ };
@@ -15,15 +15,12 @@ import {
15
15
  import {
16
16
  DiscoveryHandlers
17
17
  } from "./discovery-handlers.js";
18
- import {
19
- ProviderHandlers
20
- } from "./provider-handlers.js";
21
18
  import {
22
19
  ProvenantHandlers
23
20
  } from "./provenant-handlers.js";
24
21
  import {
25
- CrossSearchHandlers
26
- } from "./cross-search-handlers.js";
22
+ CloudSyncHandlers
23
+ } from "./cloud-sync-handlers.js";
27
24
  import {
28
25
  ContextHandlers as ContextHandlers2
29
26
  } from "./context-handlers.js";
@@ -32,9 +29,8 @@ import {
32
29
  LinearHandlers as LinearHandlers2
33
30
  } from "./linear-handlers.js";
34
31
  import { TraceHandlers as TraceHandlers2 } from "./trace-handlers.js";
35
- import { ProviderHandlers as ProviderHandlers2 } from "./provider-handlers.js";
36
32
  import { ProvenantHandlers as ProvenantHandlers2 } from "./provenant-handlers.js";
37
- import { CrossSearchHandlers as CrossSearchHandlers2 } from "./cross-search-handlers.js";
33
+ import { CloudSyncHandlers as CloudSyncHandlers2 } from "./cloud-sync-handlers.js";
38
34
  import {
39
35
  resolveToolAlias
40
36
  } from "../tool-alias-registry.js";
@@ -43,9 +39,8 @@ class MCPHandlerFactory {
43
39
  taskHandlers;
44
40
  linearHandlers;
45
41
  traceHandlers;
46
- providerHandlers;
47
42
  provenantHandlers;
48
- crossSearchHandlers;
43
+ cloudSyncHandlers;
49
44
  constructor(deps) {
50
45
  this.contextHandlers = new ContextHandlers2({
51
46
  frameManager: deps.frameManager
@@ -63,13 +58,21 @@ class MCPHandlerFactory {
63
58
  traceDetector: deps.traceDetector,
64
59
  browserMCP: deps.browserMCP
65
60
  });
66
- this.providerHandlers = new ProviderHandlers2();
67
61
  if (deps.projectDir) {
68
62
  this.provenantHandlers = new ProvenantHandlers2({
69
63
  projectDir: deps.projectDir
70
64
  });
71
65
  }
72
- this.crossSearchHandlers = new CrossSearchHandlers2({});
66
+ this.cloudSyncHandlers = new CloudSyncHandlers2({
67
+ syncManager: null
68
+ // Initialized lazily when cloud sync is configured
69
+ });
70
+ }
71
+ /**
72
+ * Set the cloud sync manager (called after config/auth is loaded)
73
+ */
74
+ setCloudSyncManager(manager) {
75
+ this.cloudSyncHandlers = new CloudSyncHandlers2({ syncManager: manager });
73
76
  }
74
77
  /**
75
78
  * Get handler for a specific tool.
@@ -133,19 +136,6 @@ class MCPHandlerFactory {
133
136
  this.traceHandlers
134
137
  );
135
138
  // Provider handlers
136
- case "delegate_to_model":
137
- return this.providerHandlers.handleDelegateToModel.bind(
138
- this.providerHandlers
139
- );
140
- case "batch_submit":
141
- return this.providerHandlers.handleBatchSubmit.bind(
142
- this.providerHandlers
143
- );
144
- case "batch_check":
145
- return this.providerHandlers.handleBatchCheck.bind(
146
- this.providerHandlers
147
- );
148
- // Provenant decision graph handlers
149
139
  case "provenant_search":
150
140
  if (!this.provenantHandlers)
151
141
  throw new Error("Provenant tools require projectDir");
@@ -171,22 +161,13 @@ class MCPHandlerFactory {
171
161
  this.provenantHandlers
172
162
  );
173
163
  // 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
- );
164
+ case "cloud_sync_push":
165
+ return this.cloudSyncHandlers.handlePush.bind(this.cloudSyncHandlers);
166
+ case "cloud_sync_pull":
167
+ return this.cloudSyncHandlers.handlePull.bind(this.cloudSyncHandlers);
168
+ case "cloud_sync_status":
169
+ return this.cloudSyncHandlers.handleStatus.bind(this.cloudSyncHandlers);
170
+ // Workflow handlers
190
171
  default:
191
172
  throw new Error(`Unknown tool: ${toolName}`);
192
173
  }
@@ -219,21 +200,16 @@ class MCPHandlerFactory {
219
200
  "take_screenshot",
220
201
  "execute_script",
221
202
  "stop_browser_debug",
222
- // Provider tools (conditionally active)
223
- "delegate_to_model",
224
- "batch_submit",
225
- "batch_check",
226
- // Provenant decision graph tools
203
+ // Provenant tools
227
204
  "provenant_search",
228
205
  "provenant_log",
229
206
  "provenant_status",
230
207
  "provenant_contradictions",
231
208
  "provenant_resolve",
232
- // Cross-project search tools
233
- "sm_cross_search",
234
- "sm_cross_discover",
235
- "sm_cross_register",
236
- "sm_cross_list"
209
+ // Cloud sync tools
210
+ "cloud_sync_push",
211
+ "cloud_sync_pull",
212
+ "cloud_sync_status"
237
213
  ];
238
214
  }
239
215
  /**
@@ -245,13 +221,12 @@ class MCPHandlerFactory {
245
221
  }
246
222
  }
247
223
  export {
224
+ CloudSyncHandlers,
248
225
  ContextHandlers,
249
- CrossSearchHandlers,
250
226
  DiscoveryHandlers,
251
227
  LinearHandlers,
252
228
  MCPHandlerFactory,
253
229
  ProvenantHandlers,
254
- ProviderHandlers,
255
230
  TaskHandlers,
256
231
  TraceHandlers
257
232
  };