@stackmemoryai/stackmemory 1.2.7 → 1.2.8
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 +3 -3
- package/dist/src/cli/commands/digest.js +73 -0
- package/dist/src/cli/index.js +2 -0
- package/dist/src/core/digest/chronological-digest.js +143 -0
- package/dist/src/core/digest/index.js +1 -0
- package/dist/src/integrations/mcp/server.js +473 -247
- package/dist/src/integrations/mcp/tool-definitions.js +567 -50
- package/package.json +2 -2
- package/templates/claude-hooks/session-rescue.sh +3 -0
- /package/templates/claude-hooks/{auto-background-hook.js → archive/auto-background-hook.js} +0 -0
- /package/templates/claude-hooks/{hook-config.json → archive/hook-config.json} +0 -0
- /package/templates/claude-hooks/{hooks.json → archive/hooks.json} +0 -0
- /package/templates/claude-hooks/{on-compact-detected → archive/on-compact-detected} +0 -0
- /package/templates/claude-hooks/{on-exit → archive/on-exit} +0 -0
- /package/templates/claude-hooks/{post-edit-sweep.js → archive/post-edit-sweep.js} +0 -0
- /package/templates/claude-hooks/{pre-tool-use → archive/pre-tool-use} +0 -0
|
@@ -31,6 +31,12 @@ import { LLMContextRetrieval } from "../../core/retrieval/index.js";
|
|
|
31
31
|
import { DiscoveryHandlers } from "./handlers/discovery-handlers.js";
|
|
32
32
|
import { DiffMemHandlers } from "./handlers/diffmem-handlers.js";
|
|
33
33
|
import { GreptileHandlers } from "./handlers/greptile-handlers.js";
|
|
34
|
+
import { CordHandlers } from "./handlers/cord-handlers.js";
|
|
35
|
+
import { TeamHandlers } from "./handlers/team-handlers.js";
|
|
36
|
+
import { SQLiteAdapter } from "../../core/database/sqlite-adapter.js";
|
|
37
|
+
import {
|
|
38
|
+
generateChronologicalDigest
|
|
39
|
+
} from "../../core/digest/chronological-digest.js";
|
|
34
40
|
import { fuzzyEdit } from "../../utils/fuzzy-edit.js";
|
|
35
41
|
import { v4 as uuidv4 } from "uuid";
|
|
36
42
|
import {
|
|
@@ -66,6 +72,8 @@ class LocalStackMemoryMCP {
|
|
|
66
72
|
diffMemHandlers;
|
|
67
73
|
greptileHandlers;
|
|
68
74
|
providerHandlers = null;
|
|
75
|
+
cordHandlers = null;
|
|
76
|
+
teamHandlers = null;
|
|
69
77
|
pendingPlans = /* @__PURE__ */ new Map();
|
|
70
78
|
constructor() {
|
|
71
79
|
this.projectRoot = this.findProjectRoot();
|
|
@@ -139,6 +147,7 @@ class LocalStackMemoryMCP {
|
|
|
139
147
|
});
|
|
140
148
|
this.diffMemHandlers = new DiffMemHandlers();
|
|
141
149
|
this.greptileHandlers = new GreptileHandlers();
|
|
150
|
+
this.initCordTeamHandlers();
|
|
142
151
|
this.initProviderHandlers();
|
|
143
152
|
this.setupHandlers();
|
|
144
153
|
this.loadInitialContext();
|
|
@@ -261,6 +270,27 @@ ${summary}...`, 0.8);
|
|
|
261
270
|
this.contexts.set(ctx.id, ctx);
|
|
262
271
|
});
|
|
263
272
|
}
|
|
273
|
+
async initCordTeamHandlers() {
|
|
274
|
+
try {
|
|
275
|
+
const dbPath = join(this.projectRoot, ".stackmemory", "context.db");
|
|
276
|
+
const adapter = new SQLiteAdapter(this.projectId, {
|
|
277
|
+
dbPath,
|
|
278
|
+
walMode: true
|
|
279
|
+
});
|
|
280
|
+
await adapter.connect();
|
|
281
|
+
this.cordHandlers = new CordHandlers({
|
|
282
|
+
frameManager: this.frameManager,
|
|
283
|
+
dbAdapter: adapter
|
|
284
|
+
});
|
|
285
|
+
this.teamHandlers = new TeamHandlers({
|
|
286
|
+
frameManager: this.frameManager,
|
|
287
|
+
dbAdapter: adapter
|
|
288
|
+
});
|
|
289
|
+
logger.info("Cord and Team handlers initialized");
|
|
290
|
+
} catch (error) {
|
|
291
|
+
logger.warn("Failed to initialize Cord/Team handlers", { error });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
264
294
|
async initProviderHandlers() {
|
|
265
295
|
if (!isFeatureEnabled("multiProvider")) return;
|
|
266
296
|
try {
|
|
@@ -296,199 +326,180 @@ ${summary}...`, 0.8);
|
|
|
296
326
|
}
|
|
297
327
|
}
|
|
298
328
|
},
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
description: "Retry loop iterations"
|
|
316
|
-
},
|
|
317
|
-
execute: {
|
|
318
|
-
type: "boolean",
|
|
319
|
-
default: false,
|
|
320
|
-
description: "Actually call implementer (otherwise dry-run)"
|
|
329
|
+
// Planning tools (only when ANTHROPIC_API_KEY is set)
|
|
330
|
+
...process.env.ANTHROPIC_API_KEY ? [
|
|
331
|
+
{
|
|
332
|
+
name: "plan_gate",
|
|
333
|
+
description: "Phase 1: Generate a plan and return an approvalId for later execution",
|
|
334
|
+
inputSchema: {
|
|
335
|
+
type: "object",
|
|
336
|
+
properties: {
|
|
337
|
+
task: {
|
|
338
|
+
type: "string",
|
|
339
|
+
description: "Task description"
|
|
340
|
+
},
|
|
341
|
+
plannerModel: {
|
|
342
|
+
type: "string",
|
|
343
|
+
description: "Claude model (optional)"
|
|
344
|
+
}
|
|
321
345
|
},
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
346
|
+
required: ["task"]
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
name: "approve_plan",
|
|
351
|
+
description: "Phase 2: Execute a previously generated plan by approvalId",
|
|
352
|
+
inputSchema: {
|
|
353
|
+
type: "object",
|
|
354
|
+
properties: {
|
|
355
|
+
approvalId: {
|
|
356
|
+
type: "string",
|
|
357
|
+
description: "Id from plan_gate"
|
|
358
|
+
},
|
|
359
|
+
implementer: {
|
|
360
|
+
type: "string",
|
|
361
|
+
enum: ["codex", "claude"],
|
|
362
|
+
default: "codex",
|
|
363
|
+
description: "Which agent implements code"
|
|
364
|
+
},
|
|
365
|
+
maxIters: { type: "number", default: 2 },
|
|
366
|
+
recordFrame: { type: "boolean", default: true },
|
|
367
|
+
execute: { type: "boolean", default: true }
|
|
326
368
|
},
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
369
|
+
required: ["approvalId"]
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
name: "pending_list",
|
|
374
|
+
description: "List pending approval-gated plans (supports filters)",
|
|
375
|
+
inputSchema: {
|
|
376
|
+
type: "object",
|
|
377
|
+
properties: {
|
|
378
|
+
taskContains: {
|
|
379
|
+
type: "string",
|
|
380
|
+
description: "Filter tasks containing this substring"
|
|
381
|
+
},
|
|
382
|
+
olderThanMs: {
|
|
383
|
+
type: "number",
|
|
384
|
+
description: "Only items older than this age (ms)"
|
|
385
|
+
},
|
|
386
|
+
newerThanMs: {
|
|
387
|
+
type: "number",
|
|
388
|
+
description: "Only items newer than this age (ms)"
|
|
389
|
+
},
|
|
390
|
+
sort: {
|
|
391
|
+
type: "string",
|
|
392
|
+
enum: ["asc", "desc"],
|
|
393
|
+
description: "Sort by createdAt"
|
|
394
|
+
},
|
|
395
|
+
limit: {
|
|
396
|
+
type: "number",
|
|
397
|
+
description: "Max items to return"
|
|
398
|
+
}
|
|
331
399
|
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: "pending_clear",
|
|
404
|
+
description: "Clear pending approval-gated plans (by id, all, or olderThanMs)",
|
|
405
|
+
inputSchema: {
|
|
406
|
+
type: "object",
|
|
407
|
+
properties: {
|
|
408
|
+
approvalId: {
|
|
409
|
+
type: "string",
|
|
410
|
+
description: "Clear a single approval by id"
|
|
411
|
+
},
|
|
412
|
+
all: {
|
|
413
|
+
type: "boolean",
|
|
414
|
+
description: "Clear all pending approvals",
|
|
415
|
+
default: false
|
|
416
|
+
},
|
|
417
|
+
olderThanMs: {
|
|
418
|
+
type: "number",
|
|
419
|
+
description: "Clear approvals older than this age (ms)"
|
|
420
|
+
}
|
|
346
421
|
}
|
|
347
|
-
},
|
|
348
|
-
required: ["task"]
|
|
349
|
-
}
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
name: "approve_plan",
|
|
353
|
-
description: "Phase 2: Execute a previously generated plan by approvalId (runs implement + critique)",
|
|
354
|
-
inputSchema: {
|
|
355
|
-
type: "object",
|
|
356
|
-
properties: {
|
|
357
|
-
approvalId: {
|
|
358
|
-
type: "string",
|
|
359
|
-
description: "Id from plan_gate"
|
|
360
|
-
},
|
|
361
|
-
implementer: {
|
|
362
|
-
type: "string",
|
|
363
|
-
enum: ["codex", "claude"],
|
|
364
|
-
default: "codex",
|
|
365
|
-
description: "Which agent implements code"
|
|
366
|
-
},
|
|
367
|
-
maxIters: { type: "number", default: 2 },
|
|
368
|
-
recordFrame: { type: "boolean", default: true },
|
|
369
|
-
execute: { type: "boolean", default: true }
|
|
370
|
-
},
|
|
371
|
-
required: ["approvalId"]
|
|
372
|
-
}
|
|
373
|
-
},
|
|
374
|
-
{
|
|
375
|
-
name: "pending_list",
|
|
376
|
-
description: "List pending approval-gated plans (supports filters)",
|
|
377
|
-
inputSchema: {
|
|
378
|
-
type: "object",
|
|
379
|
-
properties: {
|
|
380
|
-
taskContains: {
|
|
381
|
-
type: "string",
|
|
382
|
-
description: "Filter tasks containing this substring"
|
|
383
|
-
},
|
|
384
|
-
olderThanMs: {
|
|
385
|
-
type: "number",
|
|
386
|
-
description: "Only items older than this age (ms)"
|
|
387
|
-
},
|
|
388
|
-
newerThanMs: {
|
|
389
|
-
type: "number",
|
|
390
|
-
description: "Only items newer than this age (ms)"
|
|
391
|
-
},
|
|
392
|
-
sort: {
|
|
393
|
-
type: "string",
|
|
394
|
-
enum: ["asc", "desc"],
|
|
395
|
-
description: "Sort by createdAt"
|
|
396
|
-
},
|
|
397
|
-
limit: { type: "number", description: "Max items to return" }
|
|
398
422
|
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: "pending_show",
|
|
426
|
+
description: "Show a pending plan by approvalId",
|
|
427
|
+
inputSchema: {
|
|
428
|
+
type: "object",
|
|
429
|
+
properties: {
|
|
430
|
+
approvalId: {
|
|
431
|
+
type: "string",
|
|
432
|
+
description: "Approval id from plan_gate"
|
|
433
|
+
}
|
|
410
434
|
},
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
435
|
+
required: ["approvalId"]
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
name: "plan_only",
|
|
440
|
+
description: "Generate an implementation plan (Claude) and return JSON only",
|
|
441
|
+
inputSchema: {
|
|
442
|
+
type: "object",
|
|
443
|
+
properties: {
|
|
444
|
+
task: {
|
|
445
|
+
type: "string",
|
|
446
|
+
description: "Task description"
|
|
447
|
+
},
|
|
448
|
+
plannerModel: {
|
|
449
|
+
type: "string",
|
|
450
|
+
description: "Claude model for planning (optional)"
|
|
451
|
+
}
|
|
415
452
|
},
|
|
416
|
-
|
|
417
|
-
type: "number",
|
|
418
|
-
description: "Clear approvals older than this age (ms)"
|
|
419
|
-
}
|
|
453
|
+
required: ["task"]
|
|
420
454
|
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
properties: {
|
|
443
|
-
task: { type: "string", description: "Task description" },
|
|
444
|
-
plannerModel: {
|
|
445
|
-
type: "string",
|
|
446
|
-
description: "Claude model for planning (optional)"
|
|
447
|
-
}
|
|
448
|
-
},
|
|
449
|
-
required: ["task"]
|
|
450
|
-
}
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
name: "call_codex",
|
|
454
|
-
description: "Invoke Codex via codex-sm with a prompt and args; dry-run by default",
|
|
455
|
-
inputSchema: {
|
|
456
|
-
type: "object",
|
|
457
|
-
properties: {
|
|
458
|
-
prompt: { type: "string", description: "Prompt for Codex" },
|
|
459
|
-
args: {
|
|
460
|
-
type: "array",
|
|
461
|
-
items: { type: "string" },
|
|
462
|
-
description: "Additional CLI args for codex-sm"
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
name: "call_codex",
|
|
458
|
+
description: "Invoke Codex via codex-sm with a prompt and args; dry-run by default",
|
|
459
|
+
inputSchema: {
|
|
460
|
+
type: "object",
|
|
461
|
+
properties: {
|
|
462
|
+
prompt: {
|
|
463
|
+
type: "string",
|
|
464
|
+
description: "Prompt for Codex"
|
|
465
|
+
},
|
|
466
|
+
args: {
|
|
467
|
+
type: "array",
|
|
468
|
+
items: { type: "string" },
|
|
469
|
+
description: "Additional CLI args for codex-sm"
|
|
470
|
+
},
|
|
471
|
+
execute: {
|
|
472
|
+
type: "boolean",
|
|
473
|
+
default: false,
|
|
474
|
+
description: "Actually run codex-sm (otherwise dry-run)"
|
|
475
|
+
}
|
|
463
476
|
},
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
477
|
+
required: ["prompt"]
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: "call_claude",
|
|
482
|
+
description: "Invoke Claude with a prompt (Anthropic SDK)",
|
|
483
|
+
inputSchema: {
|
|
484
|
+
type: "object",
|
|
485
|
+
properties: {
|
|
486
|
+
prompt: {
|
|
487
|
+
type: "string",
|
|
488
|
+
description: "Prompt for Claude"
|
|
489
|
+
},
|
|
490
|
+
model: {
|
|
491
|
+
type: "string",
|
|
492
|
+
description: "Claude model (optional)"
|
|
493
|
+
},
|
|
494
|
+
system: {
|
|
495
|
+
type: "string",
|
|
496
|
+
description: "System prompt (optional)"
|
|
497
|
+
}
|
|
483
498
|
},
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
description: "System prompt (optional)"
|
|
487
|
-
}
|
|
488
|
-
},
|
|
489
|
-
required: ["prompt"]
|
|
499
|
+
required: ["prompt"]
|
|
500
|
+
}
|
|
490
501
|
}
|
|
491
|
-
|
|
502
|
+
] : [],
|
|
492
503
|
{
|
|
493
504
|
name: "add_decision",
|
|
494
505
|
description: "Record a decision or important information",
|
|
@@ -953,109 +964,190 @@ ${summary}...`, 0.8);
|
|
|
953
964
|
required: ["query"]
|
|
954
965
|
}
|
|
955
966
|
},
|
|
956
|
-
// DiffMem tools
|
|
967
|
+
// DiffMem tools (only when DIFFMEM_ENDPOINT or DIFFMEM_ENABLED is set)
|
|
968
|
+
...process.env.DIFFMEM_ENDPOINT || process.env.DIFFMEM_ENABLED === "true" ? this.diffMemHandlers.getToolDefinitions() : [],
|
|
969
|
+
// Cord task orchestration tools
|
|
957
970
|
{
|
|
958
|
-
name: "
|
|
959
|
-
description: "
|
|
971
|
+
name: "cord_spawn",
|
|
972
|
+
description: "Create a subtask with clean context (spawn). Child sees only its prompt and completed blocker results.",
|
|
960
973
|
inputSchema: {
|
|
961
974
|
type: "object",
|
|
962
975
|
properties: {
|
|
963
|
-
|
|
976
|
+
goal: {
|
|
977
|
+
type: "string",
|
|
978
|
+
description: "What this task should accomplish"
|
|
979
|
+
},
|
|
980
|
+
prompt: {
|
|
981
|
+
type: "string",
|
|
982
|
+
description: "Detailed instructions for the task"
|
|
983
|
+
},
|
|
984
|
+
blocked_by: {
|
|
964
985
|
type: "array",
|
|
965
|
-
items: {
|
|
966
|
-
|
|
967
|
-
enum: [
|
|
968
|
-
"preference",
|
|
969
|
-
"expertise",
|
|
970
|
-
"project_knowledge",
|
|
971
|
-
"pattern",
|
|
972
|
-
"correction"
|
|
973
|
-
]
|
|
974
|
-
},
|
|
975
|
-
description: "Filter by memory categories"
|
|
986
|
+
items: { type: "string" },
|
|
987
|
+
description: "Task IDs that must complete first"
|
|
976
988
|
},
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
description: "Maximum memories to return"
|
|
981
|
-
}
|
|
982
|
-
}
|
|
989
|
+
parent_id: { type: "string", description: "Parent task ID" }
|
|
990
|
+
},
|
|
991
|
+
required: ["goal"]
|
|
983
992
|
}
|
|
984
993
|
},
|
|
985
994
|
{
|
|
986
|
-
name: "
|
|
987
|
-
description: "
|
|
995
|
+
name: "cord_fork",
|
|
996
|
+
description: "Create a subtask with full sibling context (fork). Child sees prompt, blocker results, AND completed sibling results.",
|
|
988
997
|
inputSchema: {
|
|
989
998
|
type: "object",
|
|
990
999
|
properties: {
|
|
991
|
-
|
|
1000
|
+
goal: {
|
|
992
1001
|
type: "string",
|
|
993
|
-
description: "
|
|
1002
|
+
description: "What this task should accomplish"
|
|
994
1003
|
},
|
|
995
|
-
|
|
1004
|
+
prompt: {
|
|
996
1005
|
type: "string",
|
|
997
|
-
|
|
998
|
-
"preference",
|
|
999
|
-
"expertise",
|
|
1000
|
-
"project_knowledge",
|
|
1001
|
-
"pattern",
|
|
1002
|
-
"correction"
|
|
1003
|
-
],
|
|
1004
|
-
description: "Category of the insight"
|
|
1006
|
+
description: "Detailed instructions for the task"
|
|
1005
1007
|
},
|
|
1006
|
-
|
|
1007
|
-
type: "
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
default: 0.7,
|
|
1011
|
-
description: "Confidence level (0-1)"
|
|
1008
|
+
blocked_by: {
|
|
1009
|
+
type: "array",
|
|
1010
|
+
items: { type: "string" },
|
|
1011
|
+
description: "Task IDs that must complete first"
|
|
1012
1012
|
},
|
|
1013
|
-
|
|
1014
|
-
type: "object",
|
|
1015
|
-
description: "Additional context for the insight"
|
|
1016
|
-
}
|
|
1013
|
+
parent_id: { type: "string", description: "Parent task ID" }
|
|
1017
1014
|
},
|
|
1018
|
-
required: ["
|
|
1015
|
+
required: ["goal"]
|
|
1019
1016
|
}
|
|
1020
1017
|
},
|
|
1021
1018
|
{
|
|
1022
|
-
name: "
|
|
1023
|
-
description: "
|
|
1019
|
+
name: "cord_complete",
|
|
1020
|
+
description: "Mark a cord task as completed with a result. Automatically unblocks dependent tasks.",
|
|
1024
1021
|
inputSchema: {
|
|
1025
1022
|
type: "object",
|
|
1026
1023
|
properties: {
|
|
1027
|
-
|
|
1024
|
+
task_id: {
|
|
1028
1025
|
type: "string",
|
|
1029
|
-
description: "
|
|
1026
|
+
description: "Task ID to complete"
|
|
1030
1027
|
},
|
|
1031
|
-
|
|
1028
|
+
result: {
|
|
1032
1029
|
type: "string",
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1030
|
+
description: "The result/output of this task"
|
|
1031
|
+
}
|
|
1032
|
+
},
|
|
1033
|
+
required: ["task_id", "result"]
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
1036
|
+
{
|
|
1037
|
+
name: "cord_ask",
|
|
1038
|
+
description: "Create an ask task \u2014 a question that needs an answer before dependent tasks can proceed.",
|
|
1039
|
+
inputSchema: {
|
|
1040
|
+
type: "object",
|
|
1041
|
+
properties: {
|
|
1042
|
+
question: {
|
|
1043
|
+
type: "string",
|
|
1044
|
+
description: "The question to ask"
|
|
1036
1045
|
},
|
|
1037
|
-
|
|
1038
|
-
type: "
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1046
|
+
options: {
|
|
1047
|
+
type: "array",
|
|
1048
|
+
items: { type: "string" },
|
|
1049
|
+
description: "Optional list of answer choices"
|
|
1050
|
+
},
|
|
1051
|
+
parent_id: { type: "string", description: "Parent task ID" }
|
|
1052
|
+
},
|
|
1053
|
+
required: ["question"]
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
name: "cord_tree",
|
|
1058
|
+
description: "View the cord task tree with context scoping. Shows active, blocked, or completed tasks.",
|
|
1059
|
+
inputSchema: {
|
|
1060
|
+
type: "object",
|
|
1061
|
+
properties: {
|
|
1062
|
+
task_id: {
|
|
1063
|
+
type: "string",
|
|
1064
|
+
description: "Root task ID to show subtree (omit for full tree)"
|
|
1043
1065
|
},
|
|
1066
|
+
include_results: {
|
|
1067
|
+
type: "boolean",
|
|
1068
|
+
default: false,
|
|
1069
|
+
description: "Include task results in output"
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
},
|
|
1074
|
+
// Team collaboration tools
|
|
1075
|
+
{
|
|
1076
|
+
name: "team_context_get",
|
|
1077
|
+
description: "Get context from other agents working on the same project. Returns recent frames and shared anchors.",
|
|
1078
|
+
inputSchema: {
|
|
1079
|
+
type: "object",
|
|
1080
|
+
properties: {
|
|
1044
1081
|
limit: {
|
|
1045
1082
|
type: "number",
|
|
1046
1083
|
default: 10,
|
|
1047
|
-
description: "
|
|
1084
|
+
description: "Max frames to return"
|
|
1085
|
+
},
|
|
1086
|
+
types: {
|
|
1087
|
+
type: "array",
|
|
1088
|
+
items: { type: "string" },
|
|
1089
|
+
description: "Filter by frame types"
|
|
1090
|
+
},
|
|
1091
|
+
since: {
|
|
1092
|
+
type: "number",
|
|
1093
|
+
description: "Only frames created after this timestamp (epoch ms)"
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
},
|
|
1098
|
+
{
|
|
1099
|
+
name: "team_context_share",
|
|
1100
|
+
description: "Share a piece of context with other agents. Creates a high-priority anchor visible to team_context_get.",
|
|
1101
|
+
inputSchema: {
|
|
1102
|
+
type: "object",
|
|
1103
|
+
properties: {
|
|
1104
|
+
content: {
|
|
1105
|
+
type: "string",
|
|
1106
|
+
description: "The context to share"
|
|
1107
|
+
},
|
|
1108
|
+
type: {
|
|
1109
|
+
type: "string",
|
|
1110
|
+
enum: [
|
|
1111
|
+
"FACT",
|
|
1112
|
+
"DECISION",
|
|
1113
|
+
"CONSTRAINT",
|
|
1114
|
+
"INTERFACE_CONTRACT",
|
|
1115
|
+
"TODO",
|
|
1116
|
+
"RISK"
|
|
1117
|
+
],
|
|
1118
|
+
default: "FACT",
|
|
1119
|
+
description: "Type of context"
|
|
1120
|
+
},
|
|
1121
|
+
priority: {
|
|
1122
|
+
type: "number",
|
|
1123
|
+
minimum: 1,
|
|
1124
|
+
maximum: 10,
|
|
1125
|
+
default: 8,
|
|
1126
|
+
description: "Priority level (1-10)"
|
|
1048
1127
|
}
|
|
1049
1128
|
},
|
|
1050
|
-
required: ["
|
|
1129
|
+
required: ["content"]
|
|
1051
1130
|
}
|
|
1052
1131
|
},
|
|
1053
1132
|
{
|
|
1054
|
-
name: "
|
|
1055
|
-
description: "
|
|
1133
|
+
name: "team_search",
|
|
1134
|
+
description: "Search across all agents' context in the project. Uses full-text search across all sessions.",
|
|
1056
1135
|
inputSchema: {
|
|
1057
1136
|
type: "object",
|
|
1058
|
-
properties: {
|
|
1137
|
+
properties: {
|
|
1138
|
+
query: { type: "string", description: "Search query" },
|
|
1139
|
+
limit: {
|
|
1140
|
+
type: "number",
|
|
1141
|
+
default: 20,
|
|
1142
|
+
description: "Maximum results to return"
|
|
1143
|
+
},
|
|
1144
|
+
include_events: {
|
|
1145
|
+
type: "boolean",
|
|
1146
|
+
default: false,
|
|
1147
|
+
description: "Include events in results"
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
required: ["query"]
|
|
1059
1151
|
}
|
|
1060
1152
|
},
|
|
1061
1153
|
// Greptile tools (only active when GREPTILE_API_KEY is set)
|
|
@@ -1160,7 +1252,23 @@ ${summary}...`, 0.8);
|
|
|
1160
1252
|
required: ["batchId"]
|
|
1161
1253
|
}
|
|
1162
1254
|
}
|
|
1163
|
-
] : []
|
|
1255
|
+
] : [],
|
|
1256
|
+
// Digest tool
|
|
1257
|
+
{
|
|
1258
|
+
name: "sm_digest",
|
|
1259
|
+
description: "Generate a chronological activity digest for a time period (today/yesterday/week)",
|
|
1260
|
+
inputSchema: {
|
|
1261
|
+
type: "object",
|
|
1262
|
+
properties: {
|
|
1263
|
+
period: {
|
|
1264
|
+
type: "string",
|
|
1265
|
+
enum: ["today", "yesterday", "week"],
|
|
1266
|
+
description: "Time period for the digest"
|
|
1267
|
+
}
|
|
1268
|
+
},
|
|
1269
|
+
required: ["period"]
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1164
1272
|
]
|
|
1165
1273
|
};
|
|
1166
1274
|
}
|
|
@@ -1330,6 +1438,96 @@ ${summary}...`, 0.8);
|
|
|
1330
1438
|
case "sm_edit":
|
|
1331
1439
|
result = await this.handleSmEdit(args);
|
|
1332
1440
|
break;
|
|
1441
|
+
// Cord task orchestration
|
|
1442
|
+
case "cord_spawn":
|
|
1443
|
+
if (!this.cordHandlers) {
|
|
1444
|
+
result = {
|
|
1445
|
+
content: [
|
|
1446
|
+
{ type: "text", text: "Cord handlers not initialized." }
|
|
1447
|
+
]
|
|
1448
|
+
};
|
|
1449
|
+
} else {
|
|
1450
|
+
result = await this.cordHandlers.handleCordSpawn(args);
|
|
1451
|
+
}
|
|
1452
|
+
break;
|
|
1453
|
+
case "cord_fork":
|
|
1454
|
+
if (!this.cordHandlers) {
|
|
1455
|
+
result = {
|
|
1456
|
+
content: [
|
|
1457
|
+
{ type: "text", text: "Cord handlers not initialized." }
|
|
1458
|
+
]
|
|
1459
|
+
};
|
|
1460
|
+
} else {
|
|
1461
|
+
result = await this.cordHandlers.handleCordFork(args);
|
|
1462
|
+
}
|
|
1463
|
+
break;
|
|
1464
|
+
case "cord_complete":
|
|
1465
|
+
if (!this.cordHandlers) {
|
|
1466
|
+
result = {
|
|
1467
|
+
content: [
|
|
1468
|
+
{ type: "text", text: "Cord handlers not initialized." }
|
|
1469
|
+
]
|
|
1470
|
+
};
|
|
1471
|
+
} else {
|
|
1472
|
+
result = await this.cordHandlers.handleCordComplete(args);
|
|
1473
|
+
}
|
|
1474
|
+
break;
|
|
1475
|
+
case "cord_ask":
|
|
1476
|
+
if (!this.cordHandlers) {
|
|
1477
|
+
result = {
|
|
1478
|
+
content: [
|
|
1479
|
+
{ type: "text", text: "Cord handlers not initialized." }
|
|
1480
|
+
]
|
|
1481
|
+
};
|
|
1482
|
+
} else {
|
|
1483
|
+
result = await this.cordHandlers.handleCordAsk(args);
|
|
1484
|
+
}
|
|
1485
|
+
break;
|
|
1486
|
+
case "cord_tree":
|
|
1487
|
+
if (!this.cordHandlers) {
|
|
1488
|
+
result = {
|
|
1489
|
+
content: [
|
|
1490
|
+
{ type: "text", text: "Cord handlers not initialized." }
|
|
1491
|
+
]
|
|
1492
|
+
};
|
|
1493
|
+
} else {
|
|
1494
|
+
result = await this.cordHandlers.handleCordTree(args);
|
|
1495
|
+
}
|
|
1496
|
+
break;
|
|
1497
|
+
// Team collaboration
|
|
1498
|
+
case "team_context_get":
|
|
1499
|
+
if (!this.teamHandlers) {
|
|
1500
|
+
result = {
|
|
1501
|
+
content: [
|
|
1502
|
+
{ type: "text", text: "Team handlers not initialized." }
|
|
1503
|
+
]
|
|
1504
|
+
};
|
|
1505
|
+
} else {
|
|
1506
|
+
result = await this.teamHandlers.handleTeamContextGet(args);
|
|
1507
|
+
}
|
|
1508
|
+
break;
|
|
1509
|
+
case "team_context_share":
|
|
1510
|
+
if (!this.teamHandlers) {
|
|
1511
|
+
result = {
|
|
1512
|
+
content: [
|
|
1513
|
+
{ type: "text", text: "Team handlers not initialized." }
|
|
1514
|
+
]
|
|
1515
|
+
};
|
|
1516
|
+
} else {
|
|
1517
|
+
result = await this.teamHandlers.handleTeamContextShare(args);
|
|
1518
|
+
}
|
|
1519
|
+
break;
|
|
1520
|
+
case "team_search":
|
|
1521
|
+
if (!this.teamHandlers) {
|
|
1522
|
+
result = {
|
|
1523
|
+
content: [
|
|
1524
|
+
{ type: "text", text: "Team handlers not initialized." }
|
|
1525
|
+
]
|
|
1526
|
+
};
|
|
1527
|
+
} else {
|
|
1528
|
+
result = await this.teamHandlers.handleTeamSearch(args);
|
|
1529
|
+
}
|
|
1530
|
+
break;
|
|
1333
1531
|
// Provider tools
|
|
1334
1532
|
case "delegate_to_model":
|
|
1335
1533
|
if (!this.providerHandlers) {
|
|
@@ -1379,6 +1577,9 @@ ${summary}...`, 0.8);
|
|
|
1379
1577
|
);
|
|
1380
1578
|
}
|
|
1381
1579
|
break;
|
|
1580
|
+
case "sm_digest":
|
|
1581
|
+
result = await this.handleSmDigest(args);
|
|
1582
|
+
break;
|
|
1382
1583
|
default:
|
|
1383
1584
|
throw new Error(`Unknown tool: ${name}`);
|
|
1384
1585
|
}
|
|
@@ -2851,6 +3052,31 @@ ${typeBreakdown}`
|
|
|
2851
3052
|
matchedText: editResult.match.matchedText.length > 200 ? editResult.match.matchedText.slice(0, 200) + "..." : editResult.match.matchedText
|
|
2852
3053
|
};
|
|
2853
3054
|
}
|
|
3055
|
+
async handleSmDigest(args) {
|
|
3056
|
+
const period = String(args.period || "today");
|
|
3057
|
+
if (!["today", "yesterday", "week"].includes(period)) {
|
|
3058
|
+
return {
|
|
3059
|
+
content: [
|
|
3060
|
+
{
|
|
3061
|
+
type: "text",
|
|
3062
|
+
text: `Invalid period "${period}". Use: today, yesterday, week`
|
|
3063
|
+
}
|
|
3064
|
+
],
|
|
3065
|
+
isError: true
|
|
3066
|
+
};
|
|
3067
|
+
}
|
|
3068
|
+
const markdown = generateChronologicalDigest(
|
|
3069
|
+
this.db,
|
|
3070
|
+
period,
|
|
3071
|
+
this.projectId
|
|
3072
|
+
);
|
|
3073
|
+
const outputPath = join(this.projectRoot, ".stackmemory", `${period}.md`);
|
|
3074
|
+
writeFileSync(outputPath, markdown);
|
|
3075
|
+
return {
|
|
3076
|
+
content: [{ type: "text", text: markdown }],
|
|
3077
|
+
isError: false
|
|
3078
|
+
};
|
|
3079
|
+
}
|
|
2854
3080
|
async start() {
|
|
2855
3081
|
const transport = new StdioServerTransport();
|
|
2856
3082
|
await this.server.connect(transport);
|