@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.
- package/LICENSE +131 -64
- package/README.md +3 -1
- package/bin/claude-sm +16 -1
- package/bin/claude-smd +16 -1
- package/bin/codex-smd +16 -1
- package/bin/gemini-sm +16 -1
- package/bin/hermes-sm +21 -0
- package/bin/hermes-smd +21 -0
- package/bin/opencode-sm +16 -1
- package/dist/src/cli/codex-sm.js +51 -11
- package/dist/src/cli/commands/brain.js +206 -0
- package/dist/src/cli/commands/company-os.js +184 -0
- package/dist/src/cli/commands/context.js +5 -0
- package/dist/src/cli/commands/operator.js +127 -0
- package/dist/src/cli/commands/orchestrate.js +2 -0
- package/dist/src/cli/commands/orchestrator.js +3 -2
- package/dist/src/cli/commands/patterns.js +254 -0
- package/dist/src/cli/commands/portal.js +161 -0
- package/dist/src/cli/commands/scaffold.js +92 -0
- package/dist/src/cli/commands/setup.js +1 -4
- package/dist/src/cli/commands/sync.js +253 -0
- package/dist/src/cli/commands/tasks.js +130 -1
- package/dist/src/cli/commands/vision.js +221 -0
- package/dist/src/cli/hermes-sm.js +224 -0
- package/dist/src/cli/index.js +15 -10
- package/dist/src/cli/utils/real-cli-bin.js +72 -0
- package/dist/src/core/brain/brain-store.js +187 -0
- package/dist/src/core/brain/brain-sync.js +193 -0
- package/dist/src/core/brain/index.js +78 -0
- package/dist/src/core/brain/types.js +10 -0
- package/dist/src/core/cache/token-estimator.js +24 -1
- package/dist/src/core/config/feature-flags.js +2 -6
- package/dist/src/core/context/frame-database.js +44 -0
- package/dist/src/core/context/recursive-context-manager.js +1 -1
- package/dist/src/core/context/rehydration.js +2 -1
- package/dist/src/core/database/sqlite-adapter.js +14 -1
- package/dist/src/core/models/model-router.js +33 -1
- package/dist/src/core/models/provider-pricing.js +58 -4
- package/dist/src/core/patterns/index.js +22 -0
- package/dist/src/core/patterns/pattern-applier.js +39 -0
- package/dist/src/core/patterns/pattern-observer.js +157 -0
- package/dist/src/core/patterns/pattern-store.js +259 -0
- package/dist/src/core/patterns/types.js +19 -0
- package/dist/src/core/retrieval/llm-context-retrieval.js +5 -4
- package/dist/src/core/retrieval/unified-context-assembler.js +11 -66
- package/dist/src/core/skill-packs/types.js +14 -1
- package/dist/src/core/storage/cloud-sync-manager.js +116 -0
- package/dist/src/core/storage/cloud-sync.js +574 -0
- package/dist/src/core/storage/two-tier-storage.js +5 -1
- package/dist/src/core/tasks/master-tasks-template.js +43 -0
- package/dist/src/core/tasks/md-task-parser.js +138 -0
- package/dist/src/core/vision/index.js +27 -0
- package/dist/src/core/vision/signals.js +79 -0
- package/dist/src/core/vision/types.js +22 -0
- package/dist/src/core/vision/vision-file.js +146 -0
- package/dist/src/core/vision/vision-loop.js +220 -0
- package/dist/src/core/wiki/wiki-compiler.js +103 -1
- package/dist/src/daemon/daemon-config.js +45 -0
- package/dist/src/daemon/services/desire-path-service.js +566 -0
- package/dist/src/daemon/services/research-stream-service.js +320 -0
- package/dist/src/daemon/services/telemetry-service.js +192 -0
- package/dist/src/daemon/unified-daemon.js +28 -1
- package/dist/src/features/browser/cli-browser-agent.js +417 -0
- package/dist/src/features/browser/stagehand-workflows.js +578 -0
- package/dist/src/features/operator/adapter-factory.js +62 -0
- package/dist/src/features/operator/browser-adapter.js +109 -0
- package/dist/src/features/operator/desktop-adapter.js +125 -0
- package/dist/src/features/operator/index.js +39 -0
- package/dist/src/features/operator/llm-decision.js +137 -0
- package/dist/src/features/operator/operator-logger.js +92 -0
- package/dist/src/features/operator/overnight-runner.js +327 -0
- package/dist/src/features/operator/screen-adapter.js +91 -0
- package/dist/src/features/operator/session-manager.js +127 -0
- package/dist/src/features/operator/state-machine.js +227 -0
- package/dist/src/features/operator/task-queue.js +81 -0
- package/dist/src/features/portal/index.js +26 -0
- package/dist/src/features/portal/server.js +240 -0
- package/dist/src/features/portal/types.js +14 -0
- package/dist/src/features/portal/ui.js +195 -0
- package/dist/src/features/tasks/task-aware-context.js +2 -1
- package/dist/src/features/tui/simple-monitor.js +0 -23
- package/dist/src/features/tui/swarm-monitor.js +8 -66
- package/dist/src/{integrations/diffmem/index.js → features/web/client/hooks/use-socket.js} +6 -5
- package/dist/src/features/web/client/lib/utils.js +12 -0
- package/dist/src/features/web/client/stores/session-store.js +12 -0
- package/dist/src/features/web/server/gcp-billing.js +76 -0
- package/dist/src/features/web/server/index.js +10 -0
- package/dist/src/features/web/server/spend-calculator.js +228 -0
- package/dist/src/hooks/schemas.js +4 -1
- package/dist/src/integrations/anthropic/client.js +3 -2
- package/dist/src/integrations/claude-code/agent-bridge.js +0 -3
- package/dist/src/integrations/claude-code/subagent-client.js +218 -11
- package/dist/src/integrations/claude-code/task-coordinator.js +2 -1
- package/dist/src/integrations/linear/webhook-retry.js +196 -0
- package/dist/src/integrations/linear/webhook-server.js +18 -22
- package/dist/src/integrations/mcp/handlers/cloud-sync-handlers.js +101 -0
- package/dist/src/integrations/mcp/handlers/index.js +27 -52
- package/dist/src/integrations/mcp/server.js +122 -335
- package/dist/src/integrations/mcp/tool-alias-registry.js +0 -73
- package/dist/src/integrations/mcp/tool-definitions.js +111 -510
- package/dist/src/mcp/stackmemory-mcp-server.js +404 -379
- package/dist/src/orchestrators/multimodal/determinism.js +2 -1
- package/dist/src/orchestrators/multimodal/harness.js +2 -1
- package/dist/src/skills/recursive-agent-orchestrator.js +2 -4
- package/dist/src/utils/process-cleanup.js +1 -7
- package/docs/README.md +42 -0
- package/docs/guides/README_INSTALL.md +208 -0
- package/package.json +18 -9
- package/scripts/claude-code-wrapper.sh +11 -0
- package/scripts/claude-sm-setup.sh +12 -1
- package/scripts/codex-wrapper.sh +11 -0
- package/scripts/git-hooks/branch-context-manager.sh +11 -0
- package/scripts/git-hooks/post-checkout-stackmemory.sh +11 -0
- package/scripts/git-hooks/post-commit-stackmemory.sh +11 -0
- package/scripts/git-hooks/pre-commit-stackmemory.sh +11 -0
- package/scripts/hooks/cleanup-shell.sh +12 -1
- package/scripts/hooks/task-complete.sh +12 -1
- package/scripts/install-code-execution-hooks.sh +12 -1
- package/scripts/install-sweep-hook.sh +12 -0
- package/scripts/install.sh +11 -0
- package/scripts/opencode-wrapper.sh +11 -0
- package/scripts/portal/cloud-init.yaml +69 -0
- package/scripts/portal/setup.sh +69 -0
- package/scripts/portal/stackmemory-portal.service +34 -0
- package/scripts/setup-claude-integration.sh +12 -1
- package/scripts/smoke-init-db.sh +23 -0
- package/scripts/stackmemory-daemon.sh +11 -0
- package/scripts/verify-dist.cjs +11 -4
- package/dist/src/cli/commands/ralph.js +0 -1053
- package/dist/src/hooks/diffmem-hooks.js +0 -376
- package/dist/src/integrations/diffmem/client.js +0 -208
- package/dist/src/integrations/diffmem/config.js +0 -14
- package/dist/src/integrations/greptile/client.js +0 -101
- package/dist/src/integrations/greptile/config.js +0 -14
- package/dist/src/integrations/greptile/index.js +0 -11
- package/dist/src/integrations/mcp/handlers/cross-search-handlers.js +0 -188
- package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +0 -455
- package/dist/src/integrations/mcp/handlers/greptile-handlers.js +0 -456
- package/dist/src/integrations/mcp/handlers/provider-handlers.js +0 -227
- package/dist/src/integrations/ralph/bridge/ralph-stackmemory-bridge.js +0 -863
- package/dist/src/integrations/ralph/context/context-budget-manager.js +0 -308
- package/dist/src/integrations/ralph/context/stackmemory-context-loader.js +0 -354
- package/dist/src/integrations/ralph/index.js +0 -17
- package/dist/src/integrations/ralph/learning/pattern-learner.js +0 -416
- package/dist/src/integrations/ralph/lifecycle/iteration-lifecycle.js +0 -448
- package/dist/src/integrations/ralph/loopmax.js +0 -488
- package/dist/src/integrations/ralph/monitoring/swarm-dashboard.js +0 -293
- package/dist/src/integrations/ralph/monitoring/swarm-registry.js +0 -107
- package/dist/src/integrations/ralph/orchestration/multi-loop-orchestrator.js +0 -508
- package/dist/src/integrations/ralph/patterns/compounding-engineering-pattern.js +0 -407
- package/dist/src/integrations/ralph/patterns/extended-coherence-sessions.js +0 -495
- package/dist/src/integrations/ralph/patterns/oracle-worker-pattern.js +0 -387
- package/dist/src/integrations/ralph/performance/performance-optimizer.js +0 -357
- package/dist/src/integrations/ralph/recovery/crash-recovery.js +0 -461
- package/dist/src/integrations/ralph/state/state-reconciler.js +0 -420
- package/dist/src/integrations/ralph/swarm/git-workflow-manager.js +0 -444
- package/dist/src/integrations/ralph/swarm/swarm-coordinator.js +0 -1005
- package/dist/src/integrations/ralph/visualization/ralph-debugger.js +0 -635
- package/scripts/ralph-loop-implementation.js +0 -404
- /package/dist/src/{integrations/diffmem/types.js → core/storage/cloud-sync-types.js} +0 -0
- /package/dist/src/{integrations/greptile → features/operator}/types.js +0 -0
- /package/dist/src/{integrations/ralph/types.js → features/web/client/next-env.d.js} +0 -0
|
@@ -23,7 +23,12 @@ import {
|
|
|
23
23
|
} from "fs";
|
|
24
24
|
import { homedir } from "os";
|
|
25
25
|
import { compactPlan } from "../../orchestrators/multimodal/utils.js";
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
parseMasterTasks,
|
|
28
|
+
getNextTask,
|
|
29
|
+
addTaskToFile,
|
|
30
|
+
updateTaskInFile
|
|
31
|
+
} from "../../core/tasks/md-task-parser.js";
|
|
27
32
|
import { join, dirname } from "path";
|
|
28
33
|
import { execSync } from "child_process";
|
|
29
34
|
import { FrameManager } from "../../core/context/index.js";
|
|
@@ -35,9 +40,6 @@ import { BrowserMCPIntegration } from "../../features/browser/browser-mcp.js";
|
|
|
35
40
|
import { TraceDetector } from "../../core/trace/trace-detector.js";
|
|
36
41
|
import { LLMContextRetrieval } from "../../core/retrieval/index.js";
|
|
37
42
|
import { DiscoveryHandlers } from "./handlers/discovery-handlers.js";
|
|
38
|
-
import { DiffMemHandlers } from "./handlers/diffmem-handlers.js";
|
|
39
|
-
import { GreptileHandlers } from "./handlers/greptile-handlers.js";
|
|
40
|
-
import { CrossSearchHandlers } from "./handlers/cross-search-handlers.js";
|
|
41
43
|
import {
|
|
42
44
|
generateChronologicalDigest
|
|
43
45
|
} from "../../core/digest/chronological-digest.js";
|
|
@@ -79,13 +81,6 @@ const CACHEABLE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
79
81
|
"sm_cross_search",
|
|
80
82
|
"sm_cross_discover",
|
|
81
83
|
"sm_cross_list",
|
|
82
|
-
"diffmem_get_user_context",
|
|
83
|
-
"diffmem_search",
|
|
84
|
-
"diffmem_status",
|
|
85
|
-
"greptile_list_prs",
|
|
86
|
-
"greptile_pr_details",
|
|
87
|
-
"greptile_pr_comments",
|
|
88
|
-
"greptile_status",
|
|
89
84
|
"linear_get_tasks",
|
|
90
85
|
"linear_status",
|
|
91
86
|
"provenant_search",
|
|
@@ -106,11 +101,7 @@ class LocalStackMemoryMCP {
|
|
|
106
101
|
traceDetector;
|
|
107
102
|
contextRetrieval;
|
|
108
103
|
discoveryHandlers;
|
|
109
|
-
diffMemHandlers;
|
|
110
|
-
greptileHandlers;
|
|
111
104
|
providerHandlers = null;
|
|
112
|
-
crossSearchHandlers;
|
|
113
|
-
pendingPlans = /* @__PURE__ */ new Map();
|
|
114
105
|
contentCache;
|
|
115
106
|
traceEventStore;
|
|
116
107
|
sessionId;
|
|
@@ -190,10 +181,6 @@ class LocalStackMemoryMCP {
|
|
|
190
181
|
db: this.db,
|
|
191
182
|
projectRoot: this.projectRoot
|
|
192
183
|
});
|
|
193
|
-
this.diffMemHandlers = new DiffMemHandlers();
|
|
194
|
-
this.greptileHandlers = new GreptileHandlers();
|
|
195
|
-
this.crossSearchHandlers = new CrossSearchHandlers({});
|
|
196
|
-
this.initProviderHandlers();
|
|
197
184
|
this.setupHandlers();
|
|
198
185
|
this.loadInitialContext();
|
|
199
186
|
this.loadPendingPlans();
|
|
@@ -416,16 +403,6 @@ ${summary}...`, 0.8);
|
|
|
416
403
|
this.contexts.set(ctx.id, ctx);
|
|
417
404
|
});
|
|
418
405
|
}
|
|
419
|
-
async initProviderHandlers() {
|
|
420
|
-
if (!isFeatureEnabled("multiProvider")) return;
|
|
421
|
-
try {
|
|
422
|
-
const { ProviderHandlers } = await import("./handlers/provider-handlers.js");
|
|
423
|
-
this.providerHandlers = new ProviderHandlers();
|
|
424
|
-
logger.info("Provider handlers initialized (multiProvider enabled)");
|
|
425
|
-
} catch (error) {
|
|
426
|
-
logger.warn("Failed to initialize provider handlers", { error });
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
406
|
setupHandlers() {
|
|
430
407
|
this.server.setRequestHandler(
|
|
431
408
|
z.object({
|
|
@@ -454,7 +431,6 @@ ${summary}...`, 0.8);
|
|
|
454
431
|
// Planning tools (only when ANTHROPIC_API_KEY is set)
|
|
455
432
|
...process.env.ANTHROPIC_API_KEY ? [
|
|
456
433
|
{
|
|
457
|
-
name: "plan_gate",
|
|
458
434
|
description: "Phase 1: Generate a plan and return an approvalId for later execution",
|
|
459
435
|
inputSchema: {
|
|
460
436
|
type: "object",
|
|
@@ -472,14 +448,12 @@ ${summary}...`, 0.8);
|
|
|
472
448
|
}
|
|
473
449
|
},
|
|
474
450
|
{
|
|
475
|
-
name: "approve_plan",
|
|
476
451
|
description: "Phase 2: Execute a previously generated plan by approvalId",
|
|
477
452
|
inputSchema: {
|
|
478
453
|
type: "object",
|
|
479
454
|
properties: {
|
|
480
455
|
approvalId: {
|
|
481
|
-
type: "string"
|
|
482
|
-
description: "Id from plan_gate"
|
|
456
|
+
type: "string"
|
|
483
457
|
},
|
|
484
458
|
implementer: {
|
|
485
459
|
type: "string",
|
|
@@ -558,15 +532,13 @@ ${summary}...`, 0.8);
|
|
|
558
532
|
type: "object",
|
|
559
533
|
properties: {
|
|
560
534
|
approvalId: {
|
|
561
|
-
type: "string"
|
|
562
|
-
description: "Approval id from plan_gate"
|
|
535
|
+
type: "string"
|
|
563
536
|
}
|
|
564
537
|
},
|
|
565
538
|
required: ["approvalId"]
|
|
566
539
|
}
|
|
567
540
|
},
|
|
568
541
|
{
|
|
569
|
-
name: "plan_only",
|
|
570
542
|
description: "Generate an implementation plan (Claude) and return JSON only",
|
|
571
543
|
inputSchema: {
|
|
572
544
|
type: "object",
|
|
@@ -584,7 +556,6 @@ ${summary}...`, 0.8);
|
|
|
584
556
|
}
|
|
585
557
|
},
|
|
586
558
|
{
|
|
587
|
-
name: "call_codex",
|
|
588
559
|
description: "Invoke Codex via codex-sm with a prompt and args; dry-run by default",
|
|
589
560
|
inputSchema: {
|
|
590
561
|
type: "object",
|
|
@@ -608,7 +579,6 @@ ${summary}...`, 0.8);
|
|
|
608
579
|
}
|
|
609
580
|
},
|
|
610
581
|
{
|
|
611
|
-
name: "call_claude",
|
|
612
582
|
description: "Invoke Claude with a prompt (Anthropic SDK)",
|
|
613
583
|
inputSchema: {
|
|
614
584
|
type: "object",
|
|
@@ -1094,10 +1064,8 @@ ${summary}...`, 0.8);
|
|
|
1094
1064
|
required: ["query"]
|
|
1095
1065
|
}
|
|
1096
1066
|
},
|
|
1097
|
-
// DiffMem tools (only when DIFFMEM_ENDPOINT or DIFFMEM_ENABLED is set)
|
|
1098
1067
|
...process.env.DIFFMEM_ENDPOINT || process.env.DIFFMEM_ENABLED === "true" ? this.diffMemHandlers.getToolDefinitions() : [],
|
|
1099
1068
|
// Greptile tools (only active when GREPTILE_API_KEY is set)
|
|
1100
|
-
...process.env.GREPTILE_API_KEY ? this.greptileHandlers.getToolDefinitions() : [],
|
|
1101
1069
|
// Provider tools (only active when STACKMEMORY_MULTI_PROVIDER=true)
|
|
1102
1070
|
...isFeatureEnabled("multiProvider") ? [
|
|
1103
1071
|
{
|
|
@@ -1483,20 +1451,10 @@ ${summary}...`, 0.8);
|
|
|
1483
1451
|
case "compress_old_traces":
|
|
1484
1452
|
result = await this.handleCompressOldTraces(args);
|
|
1485
1453
|
break;
|
|
1486
|
-
case "plan_only":
|
|
1487
|
-
result = await this.handlePlanOnly(args);
|
|
1488
1454
|
break;
|
|
1489
|
-
case "call_codex":
|
|
1490
|
-
result = await this.handleCallCodex(args);
|
|
1491
1455
|
break;
|
|
1492
|
-
case "call_claude":
|
|
1493
|
-
result = await this.handleCallClaude(args);
|
|
1494
1456
|
break;
|
|
1495
|
-
case "plan_gate":
|
|
1496
|
-
result = await this.handlePlanGate(args);
|
|
1497
1457
|
break;
|
|
1498
|
-
case "approve_plan":
|
|
1499
|
-
result = await this.handleApprovePlan(args);
|
|
1500
1458
|
break;
|
|
1501
1459
|
case "pending_list":
|
|
1502
1460
|
result = await this.handlePendingList();
|
|
@@ -1526,41 +1484,15 @@ ${summary}...`, 0.8);
|
|
|
1526
1484
|
case "sm_search":
|
|
1527
1485
|
result = await this.handleSmSearch(args);
|
|
1528
1486
|
break;
|
|
1529
|
-
// DiffMem handlers
|
|
1530
|
-
case "diffmem_get_user_context":
|
|
1531
1487
|
result = await this.diffMemHandlers.handleGetUserContext(args);
|
|
1532
1488
|
break;
|
|
1533
|
-
case "diffmem_store_learning":
|
|
1534
1489
|
result = await this.diffMemHandlers.handleStoreLearning(args);
|
|
1535
1490
|
break;
|
|
1536
|
-
case "diffmem_search":
|
|
1537
1491
|
result = await this.diffMemHandlers.handleSearch(args);
|
|
1538
1492
|
break;
|
|
1539
|
-
case "diffmem_status":
|
|
1540
1493
|
result = await this.diffMemHandlers.handleStatus();
|
|
1541
1494
|
break;
|
|
1542
1495
|
// Greptile handlers
|
|
1543
|
-
case "greptile_pr_comments":
|
|
1544
|
-
result = await this.greptileHandlers.handleListPRComments(args);
|
|
1545
|
-
break;
|
|
1546
|
-
case "greptile_pr_details":
|
|
1547
|
-
result = await this.greptileHandlers.handleGetMergeRequest(args);
|
|
1548
|
-
break;
|
|
1549
|
-
case "greptile_list_prs":
|
|
1550
|
-
result = await this.greptileHandlers.handleListPullRequests(args);
|
|
1551
|
-
break;
|
|
1552
|
-
case "greptile_trigger_review":
|
|
1553
|
-
result = await this.greptileHandlers.handleTriggerCodeReview(args);
|
|
1554
|
-
break;
|
|
1555
|
-
case "greptile_search_patterns":
|
|
1556
|
-
result = await this.greptileHandlers.handleSearchPatterns(args);
|
|
1557
|
-
break;
|
|
1558
|
-
case "greptile_create_pattern":
|
|
1559
|
-
result = await this.greptileHandlers.handleCreatePattern(args);
|
|
1560
|
-
break;
|
|
1561
|
-
case "greptile_status":
|
|
1562
|
-
result = await this.greptileHandlers.handleStatus();
|
|
1563
|
-
break;
|
|
1564
1496
|
case "sm_edit":
|
|
1565
1497
|
result = await this.handleSmEdit(args);
|
|
1566
1498
|
break;
|
|
@@ -1651,6 +1583,15 @@ ${summary}...`, 0.8);
|
|
|
1651
1583
|
case "trace_event_annotate":
|
|
1652
1584
|
result = this.handleTraceEventAnnotate(args);
|
|
1653
1585
|
break;
|
|
1586
|
+
case "get_next_master_task":
|
|
1587
|
+
result = this.handleGetNextMasterTask(args);
|
|
1588
|
+
break;
|
|
1589
|
+
case "update_master_task":
|
|
1590
|
+
result = this.handleUpdateMasterTask(args);
|
|
1591
|
+
break;
|
|
1592
|
+
case "create_master_task":
|
|
1593
|
+
result = this.handleCreateMasterTask(args);
|
|
1594
|
+
break;
|
|
1654
1595
|
default:
|
|
1655
1596
|
throw new Error(`Unknown tool: ${name}`);
|
|
1656
1597
|
}
|
|
@@ -1795,60 +1736,6 @@ ${summary}...`, 0.8);
|
|
|
1795
1736
|
isError: false
|
|
1796
1737
|
};
|
|
1797
1738
|
}
|
|
1798
|
-
async handlePlanOnly(args) {
|
|
1799
|
-
const { runPlanOnly } = await import("../../orchestrators/multimodal/harness.js");
|
|
1800
|
-
const task = String(args.task || "Plan change");
|
|
1801
|
-
const plannerModel = args.plannerModel || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL;
|
|
1802
|
-
const plan = await runPlanOnly(
|
|
1803
|
-
{ task, repoPath: this.projectRoot },
|
|
1804
|
-
{ plannerModel }
|
|
1805
|
-
);
|
|
1806
|
-
return {
|
|
1807
|
-
content: [
|
|
1808
|
-
{
|
|
1809
|
-
type: "text",
|
|
1810
|
-
text: JSON.stringify({ ok: true, plan })
|
|
1811
|
-
}
|
|
1812
|
-
],
|
|
1813
|
-
isError: false
|
|
1814
|
-
};
|
|
1815
|
-
}
|
|
1816
|
-
async handleCallCodex(args) {
|
|
1817
|
-
const { callCodexCLI } = await import("../../orchestrators/multimodal/providers.js");
|
|
1818
|
-
const prompt = String(args.prompt || "");
|
|
1819
|
-
const extraArgs = Array.isArray(args.args) ? args.args : [];
|
|
1820
|
-
const execute = Boolean(args.execute);
|
|
1821
|
-
const resp = callCodexCLI(prompt, extraArgs, !execute);
|
|
1822
|
-
return {
|
|
1823
|
-
content: [
|
|
1824
|
-
{
|
|
1825
|
-
type: "text",
|
|
1826
|
-
text: JSON.stringify({
|
|
1827
|
-
ok: resp.ok,
|
|
1828
|
-
command: resp.command,
|
|
1829
|
-
output: resp.output
|
|
1830
|
-
})
|
|
1831
|
-
}
|
|
1832
|
-
],
|
|
1833
|
-
isError: false
|
|
1834
|
-
};
|
|
1835
|
-
}
|
|
1836
|
-
async handleCallClaude(args) {
|
|
1837
|
-
const { callClaude } = await import("../../orchestrators/multimodal/providers.js");
|
|
1838
|
-
const prompt = String(args.prompt || "");
|
|
1839
|
-
const model = args.model || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL;
|
|
1840
|
-
const system = args.system || "You are a precise assistant. Return plain text unless asked for JSON.";
|
|
1841
|
-
const text = await callClaude(prompt, { model, system });
|
|
1842
|
-
return {
|
|
1843
|
-
content: [
|
|
1844
|
-
{
|
|
1845
|
-
type: "text",
|
|
1846
|
-
text: JSON.stringify({ ok: true, text })
|
|
1847
|
-
}
|
|
1848
|
-
],
|
|
1849
|
-
isError: false
|
|
1850
|
-
};
|
|
1851
|
-
}
|
|
1852
1739
|
// Pending plan persistence (best-effort)
|
|
1853
1740
|
getPendingStoreDir() {
|
|
1854
1741
|
return join(this.projectRoot, ".stackmemory", "build");
|
|
@@ -1872,7 +1759,6 @@ ${summary}...`, 0.8);
|
|
|
1872
1759
|
}
|
|
1873
1760
|
const data = JSON.parse(readFileSync(sourceFile, "utf-8"));
|
|
1874
1761
|
if (data && typeof data === "object") {
|
|
1875
|
-
this.pendingPlans = new Map(Object.entries(data));
|
|
1876
1762
|
if (sourceFile !== file) this.savePendingPlans();
|
|
1877
1763
|
}
|
|
1878
1764
|
} catch {
|
|
@@ -1883,214 +1769,11 @@ ${summary}...`, 0.8);
|
|
|
1883
1769
|
const dir = this.getPendingStoreDir();
|
|
1884
1770
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
1885
1771
|
const file = this.getPendingStorePath();
|
|
1886
|
-
const obj = Object.fromEntries(this.pendingPlans);
|
|
1887
1772
|
writeFileSync(file, JSON.stringify(obj, null, 2));
|
|
1888
1773
|
} catch {
|
|
1889
1774
|
}
|
|
1890
1775
|
}
|
|
1891
|
-
|
|
1892
|
-
const { runPlanOnly } = await import("../../orchestrators/multimodal/harness.js");
|
|
1893
|
-
const task = String(args.task || "Plan change");
|
|
1894
|
-
const plannerModel = args.plannerModel || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL;
|
|
1895
|
-
const plan = await runPlanOnly(
|
|
1896
|
-
{ task, repoPath: this.projectRoot },
|
|
1897
|
-
{ plannerModel }
|
|
1898
|
-
);
|
|
1899
|
-
const approvalId = `appr_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
1900
|
-
this.pendingPlans.set(approvalId, { task, plan, createdAt: Date.now() });
|
|
1901
|
-
this.savePendingPlans();
|
|
1902
|
-
const compact = Boolean(args.compact);
|
|
1903
|
-
const planOut = compact ? compactPlan(plan) : plan;
|
|
1904
|
-
return {
|
|
1905
|
-
content: [
|
|
1906
|
-
{
|
|
1907
|
-
type: "text",
|
|
1908
|
-
text: JSON.stringify({ ok: true, approvalId, plan: planOut })
|
|
1909
|
-
}
|
|
1910
|
-
],
|
|
1911
|
-
isError: false
|
|
1912
|
-
};
|
|
1913
|
-
}
|
|
1914
|
-
async handleApprovePlan(args) {
|
|
1915
|
-
const { runSpike } = await import("../../orchestrators/multimodal/harness.js");
|
|
1916
|
-
const approvalId = String(args.approvalId || "");
|
|
1917
|
-
const pending = this.pendingPlans.get(approvalId);
|
|
1918
|
-
if (!pending) {
|
|
1919
|
-
return {
|
|
1920
|
-
content: [
|
|
1921
|
-
{
|
|
1922
|
-
type: "text",
|
|
1923
|
-
text: JSON.stringify({ ok: false, error: "Invalid approvalId" })
|
|
1924
|
-
}
|
|
1925
|
-
],
|
|
1926
|
-
isError: false
|
|
1927
|
-
};
|
|
1928
|
-
}
|
|
1929
|
-
const implementer = args.implementer || process.env["STACKMEMORY_MM_IMPLEMENTER"] || DEFAULT_IMPLEMENTER;
|
|
1930
|
-
const maxIters = Number(
|
|
1931
|
-
args.maxIters ?? process.env["STACKMEMORY_MM_MAX_ITERS"] ?? DEFAULT_MAX_ITERS
|
|
1932
|
-
);
|
|
1933
|
-
const recordFrame = args.recordFrame !== false;
|
|
1934
|
-
const execute = args.execute !== false;
|
|
1935
|
-
const verificationCommands = this.getVerificationCommands(args);
|
|
1936
|
-
const result = await runSpike(
|
|
1937
|
-
{ task: pending.task, repoPath: this.projectRoot },
|
|
1938
|
-
{
|
|
1939
|
-
plannerModel: process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL,
|
|
1940
|
-
reviewerModel: process.env["STACKMEMORY_MM_REVIEWER_MODEL"] || process.env["STACKMEMORY_MM_PLANNER_MODEL"] || DEFAULT_PLANNER_MODEL,
|
|
1941
|
-
implementer: implementer === "claude" ? "claude" : "codex",
|
|
1942
|
-
maxIters: isFinite(maxIters) ? Math.max(1, maxIters) : 2,
|
|
1943
|
-
dryRun: !execute,
|
|
1944
|
-
verificationCommands,
|
|
1945
|
-
recordFrame
|
|
1946
|
-
}
|
|
1947
|
-
);
|
|
1948
|
-
this.pendingPlans.delete(approvalId);
|
|
1949
|
-
this.savePendingPlans();
|
|
1950
|
-
const compact = Boolean(args.compact);
|
|
1951
|
-
const payload = compact ? { ...result, plan: compactPlan(result.plan) } : result;
|
|
1952
|
-
return {
|
|
1953
|
-
content: [
|
|
1954
|
-
{
|
|
1955
|
-
type: "text",
|
|
1956
|
-
text: JSON.stringify({ ok: true, approvalId, result: payload })
|
|
1957
|
-
}
|
|
1958
|
-
],
|
|
1959
|
-
isError: false
|
|
1960
|
-
};
|
|
1961
|
-
}
|
|
1962
|
-
async handlePendingList(args) {
|
|
1963
|
-
const schema = z.object({
|
|
1964
|
-
taskContains: z.string().optional(),
|
|
1965
|
-
olderThanMs: z.number().optional(),
|
|
1966
|
-
newerThanMs: z.number().optional(),
|
|
1967
|
-
sort: z.enum(["asc", "desc"]).optional(),
|
|
1968
|
-
limit: z.number().int().positive().optional()
|
|
1969
|
-
}).optional();
|
|
1970
|
-
const parsed = schema.safeParse(args);
|
|
1971
|
-
if (args && !parsed.success) {
|
|
1972
|
-
return {
|
|
1973
|
-
content: [
|
|
1974
|
-
{
|
|
1975
|
-
type: "text",
|
|
1976
|
-
text: JSON.stringify({
|
|
1977
|
-
ok: false,
|
|
1978
|
-
error: "Invalid arguments",
|
|
1979
|
-
details: parsed.error.issues
|
|
1980
|
-
})
|
|
1981
|
-
}
|
|
1982
|
-
],
|
|
1983
|
-
isError: false
|
|
1984
|
-
};
|
|
1985
|
-
}
|
|
1986
|
-
const a = parsed.success && parsed.data ? parsed.data : {};
|
|
1987
|
-
const now = Date.now();
|
|
1988
|
-
let items = Array.from(this.pendingPlans.entries()).map(
|
|
1989
|
-
([approvalId, data]) => ({
|
|
1990
|
-
approvalId,
|
|
1991
|
-
task: data?.task,
|
|
1992
|
-
createdAt: Number(data?.createdAt || 0) || null
|
|
1993
|
-
})
|
|
1994
|
-
);
|
|
1995
|
-
items = filterPending(items, a, now);
|
|
1996
|
-
return {
|
|
1997
|
-
content: [
|
|
1998
|
-
{ type: "text", text: JSON.stringify({ ok: true, pending: items }) }
|
|
1999
|
-
],
|
|
2000
|
-
isError: false
|
|
2001
|
-
};
|
|
2002
|
-
}
|
|
2003
|
-
async handlePendingClear(args) {
|
|
2004
|
-
const removed = [];
|
|
2005
|
-
const now = Date.now();
|
|
2006
|
-
const all = Boolean(args?.all);
|
|
2007
|
-
const approvalId = args?.approvalId ? String(args.approvalId) : void 0;
|
|
2008
|
-
const olderThanMs = Number.isFinite(Number(args?.olderThanMs)) ? Number(args.olderThanMs) : void 0;
|
|
2009
|
-
if (all) {
|
|
2010
|
-
for (const id of this.pendingPlans.keys()) removed.push(id);
|
|
2011
|
-
this.pendingPlans.clear();
|
|
2012
|
-
this.savePendingPlans();
|
|
2013
|
-
return {
|
|
2014
|
-
content: [
|
|
2015
|
-
{ type: "text", text: JSON.stringify({ ok: true, removed }) }
|
|
2016
|
-
],
|
|
2017
|
-
isError: false
|
|
2018
|
-
};
|
|
2019
|
-
}
|
|
2020
|
-
if (approvalId) {
|
|
2021
|
-
if (this.pendingPlans.has(approvalId)) {
|
|
2022
|
-
this.pendingPlans.delete(approvalId);
|
|
2023
|
-
removed.push(approvalId);
|
|
2024
|
-
this.savePendingPlans();
|
|
2025
|
-
}
|
|
2026
|
-
return {
|
|
2027
|
-
content: [
|
|
2028
|
-
{ type: "text", text: JSON.stringify({ ok: true, removed }) }
|
|
2029
|
-
],
|
|
2030
|
-
isError: false
|
|
2031
|
-
};
|
|
2032
|
-
}
|
|
2033
|
-
if (olderThanMs !== void 0 && olderThanMs >= 0) {
|
|
2034
|
-
for (const [id, data] of this.pendingPlans.entries()) {
|
|
2035
|
-
const ts = Number(data?.createdAt || 0);
|
|
2036
|
-
if (ts && now - ts > olderThanMs) {
|
|
2037
|
-
this.pendingPlans.delete(id);
|
|
2038
|
-
removed.push(id);
|
|
2039
|
-
}
|
|
2040
|
-
}
|
|
2041
|
-
this.savePendingPlans();
|
|
2042
|
-
return {
|
|
2043
|
-
content: [
|
|
2044
|
-
{ type: "text", text: JSON.stringify({ ok: true, removed }) }
|
|
2045
|
-
],
|
|
2046
|
-
isError: false
|
|
2047
|
-
};
|
|
2048
|
-
}
|
|
2049
|
-
return {
|
|
2050
|
-
content: [
|
|
2051
|
-
{
|
|
2052
|
-
type: "text",
|
|
2053
|
-
text: JSON.stringify({
|
|
2054
|
-
ok: false,
|
|
2055
|
-
error: "Specify approvalId, all=true, or olderThanMs"
|
|
2056
|
-
})
|
|
2057
|
-
}
|
|
2058
|
-
],
|
|
2059
|
-
isError: false
|
|
2060
|
-
};
|
|
2061
|
-
}
|
|
2062
|
-
async handlePendingShow(args) {
|
|
2063
|
-
const approvalId = String(args?.approvalId || "");
|
|
2064
|
-
const data = this.pendingPlans.get(approvalId);
|
|
2065
|
-
if (!data) {
|
|
2066
|
-
return {
|
|
2067
|
-
content: [
|
|
2068
|
-
{
|
|
2069
|
-
type: "text",
|
|
2070
|
-
text: JSON.stringify({ ok: false, error: "Invalid approvalId" })
|
|
2071
|
-
}
|
|
2072
|
-
],
|
|
2073
|
-
isError: false
|
|
2074
|
-
};
|
|
2075
|
-
}
|
|
2076
|
-
const compact = Boolean(args.compact);
|
|
2077
|
-
const planOut = compact ? compactPlan(data.plan) : data.plan;
|
|
2078
|
-
return {
|
|
2079
|
-
content: [
|
|
2080
|
-
{
|
|
2081
|
-
type: "text",
|
|
2082
|
-
text: JSON.stringify({
|
|
2083
|
-
ok: true,
|
|
2084
|
-
approvalId,
|
|
2085
|
-
task: data.task,
|
|
2086
|
-
plan: planOut,
|
|
2087
|
-
createdAt: data.createdAt || null
|
|
2088
|
-
})
|
|
2089
|
-
}
|
|
2090
|
-
],
|
|
2091
|
-
isError: false
|
|
2092
|
-
};
|
|
2093
|
-
}
|
|
1776
|
+
// [REMOVED in v1.14] Conductor/multimodal handlers + pending plan handlers
|
|
2094
1777
|
async handleGetContext(args) {
|
|
2095
1778
|
const { query: query2 = "", limit = 10 } = args;
|
|
2096
1779
|
const contexts = Array.from(this.contexts.values()).sort((a, b) => b.importance - a.importance).slice(0, limit);
|
|
@@ -3456,6 +3139,110 @@ ${catLines.join("\n")}`
|
|
|
3456
3139
|
process.on("SIGTERM", printCacheSummary);
|
|
3457
3140
|
process.on("exit", printCacheSummary);
|
|
3458
3141
|
}
|
|
3142
|
+
// ── Master Task Handlers ───────────────────────────────────
|
|
3143
|
+
resolveMasterTasksPath() {
|
|
3144
|
+
const smPath = join(
|
|
3145
|
+
this.projectRoot,
|
|
3146
|
+
".stackmemory",
|
|
3147
|
+
"tasks",
|
|
3148
|
+
"master-tasks.md"
|
|
3149
|
+
);
|
|
3150
|
+
if (existsSync(smPath)) return smPath;
|
|
3151
|
+
const rootPath = join(this.projectRoot, "master-tasks.md");
|
|
3152
|
+
if (existsSync(rootPath)) return rootPath;
|
|
3153
|
+
return null;
|
|
3154
|
+
}
|
|
3155
|
+
handleGetNextMasterTask(args) {
|
|
3156
|
+
const mdPath = this.resolveMasterTasksPath();
|
|
3157
|
+
if (!mdPath) {
|
|
3158
|
+
return {
|
|
3159
|
+
content: [
|
|
3160
|
+
{
|
|
3161
|
+
type: "text",
|
|
3162
|
+
text: 'No master-tasks.md found. Run "stackmemory tasks init" to create one.'
|
|
3163
|
+
}
|
|
3164
|
+
]
|
|
3165
|
+
};
|
|
3166
|
+
}
|
|
3167
|
+
let tasks = parseMasterTasks(readFileSync(mdPath, "utf-8"));
|
|
3168
|
+
if (args.owner) {
|
|
3169
|
+
tasks = tasks.filter((t) => t.owner === String(args.owner));
|
|
3170
|
+
}
|
|
3171
|
+
const next = getNextTask(tasks);
|
|
3172
|
+
if (!next) {
|
|
3173
|
+
return {
|
|
3174
|
+
content: [{ type: "text", text: "No actionable tasks found." }]
|
|
3175
|
+
};
|
|
3176
|
+
}
|
|
3177
|
+
return {
|
|
3178
|
+
content: [{ type: "text", text: JSON.stringify(next, null, 2) }]
|
|
3179
|
+
};
|
|
3180
|
+
}
|
|
3181
|
+
handleUpdateMasterTask(args) {
|
|
3182
|
+
const mdPath = this.resolveMasterTasksPath();
|
|
3183
|
+
if (!mdPath) {
|
|
3184
|
+
return {
|
|
3185
|
+
content: [{ type: "text", text: "No master-tasks.md found." }]
|
|
3186
|
+
};
|
|
3187
|
+
}
|
|
3188
|
+
const taskId = String(args.task_id || "").toUpperCase();
|
|
3189
|
+
if (!taskId) {
|
|
3190
|
+
return {
|
|
3191
|
+
content: [{ type: "text", text: "task_id is required." }],
|
|
3192
|
+
isError: true
|
|
3193
|
+
};
|
|
3194
|
+
}
|
|
3195
|
+
const updates = {};
|
|
3196
|
+
if (args.status) updates.status = String(args.status);
|
|
3197
|
+
if (args.priority) updates.priority = String(args.priority);
|
|
3198
|
+
if (args.owner) updates.owner = String(args.owner);
|
|
3199
|
+
if (args.branch_pr) updates.branchPr = String(args.branch_pr);
|
|
3200
|
+
if (args.notes) updates.notes = String(args.notes);
|
|
3201
|
+
if (args.sync) updates.sync = String(args.sync);
|
|
3202
|
+
try {
|
|
3203
|
+
updateTaskInFile(mdPath, taskId, updates);
|
|
3204
|
+
return {
|
|
3205
|
+
content: [{ type: "text", text: `Updated ${taskId}` }]
|
|
3206
|
+
};
|
|
3207
|
+
} catch (err) {
|
|
3208
|
+
return {
|
|
3209
|
+
content: [{ type: "text", text: err.message }],
|
|
3210
|
+
isError: true
|
|
3211
|
+
};
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
handleCreateMasterTask(args) {
|
|
3215
|
+
const mdPath = this.resolveMasterTasksPath();
|
|
3216
|
+
if (!mdPath) {
|
|
3217
|
+
return {
|
|
3218
|
+
content: [
|
|
3219
|
+
{
|
|
3220
|
+
type: "text",
|
|
3221
|
+
text: 'No master-tasks.md found. Run "stackmemory tasks init" to create one.'
|
|
3222
|
+
}
|
|
3223
|
+
]
|
|
3224
|
+
};
|
|
3225
|
+
}
|
|
3226
|
+
const task = String(args.task || "");
|
|
3227
|
+
if (!task) {
|
|
3228
|
+
return {
|
|
3229
|
+
content: [{ type: "text", text: "task description is required." }],
|
|
3230
|
+
isError: true
|
|
3231
|
+
};
|
|
3232
|
+
}
|
|
3233
|
+
const id = addTaskToFile(mdPath, {
|
|
3234
|
+
priority: String(args.priority || "P1"),
|
|
3235
|
+
status: "todo",
|
|
3236
|
+
owner: String(args.owner || "@me"),
|
|
3237
|
+
sync: String(args.sync || "local"),
|
|
3238
|
+
task,
|
|
3239
|
+
branchPr: "",
|
|
3240
|
+
notes: String(args.notes || "")
|
|
3241
|
+
});
|
|
3242
|
+
return {
|
|
3243
|
+
content: [{ type: "text", text: `Created ${id}: ${task}` }]
|
|
3244
|
+
};
|
|
3245
|
+
}
|
|
3459
3246
|
}
|
|
3460
3247
|
var server_default = LocalStackMemoryMCP;
|
|
3461
3248
|
async function runMCPServer() {
|