@stitchdb/cli 0.8.0 → 0.10.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/dist/cli.js +57 -10
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -628,6 +628,7 @@ async function cmdHook(args) {
|
|
|
628
628
|
try {
|
|
629
629
|
const stitch = client(cfg);
|
|
630
630
|
const projectTag = (threadName.split('/')[0] || threadName).toLowerCase();
|
|
631
|
+
const baseUrl = cfg.baseUrl || 'https://db.stitchdb.com';
|
|
631
632
|
const [thread, memHits, workspaces, fileSummaries, aboutMems] = await Promise.all([
|
|
632
633
|
stitch.thread(threadName).recall({ last: 5 }).catch(() => ({ thread_id: '', recent: [], semantic: [] })),
|
|
633
634
|
stitch.recall(projectTag, { k: 8 }).catch(() => []),
|
|
@@ -635,10 +636,26 @@ async function cmdHook(args) {
|
|
|
635
636
|
stitch.list({ limit: 12 }).then((all) => all.filter((m) => m.tags.some((t) => t.startsWith('file:')))).catch(() => []),
|
|
636
637
|
stitch.list({ tag: 'workspace:about', limit: 1 }).catch(() => []),
|
|
637
638
|
]);
|
|
638
|
-
|
|
639
|
+
// Look up the current workspace using the client's resolved id; fall
|
|
640
|
+
// back to first if resolveWorkspace failed (shouldn't normally).
|
|
641
|
+
const currentWsId = await stitch.resolveWorkspace().catch(() => null);
|
|
642
|
+
const currentWs = (Array.isArray(workspaces) ? workspaces : [])
|
|
643
|
+
.find((w) => w.id === currentWsId) || (Array.isArray(workspaces) ? workspaces[0] : null);
|
|
644
|
+
// Cross-project user-level memories from the special `_global` workspace.
|
|
645
|
+
// Pull top 8 most-recent — these are user preferences / rules that apply
|
|
646
|
+
// EVERYWHERE, regardless of which project this session is in.
|
|
647
|
+
let globalMems = [];
|
|
648
|
+
try {
|
|
649
|
+
const globalWs = (Array.isArray(workspaces) ? workspaces : []).find((w) => w.name === '_global');
|
|
650
|
+
if (globalWs) {
|
|
651
|
+
const globalClient = new Stitch({ apiKey: cfg.apiKey, baseUrl, workspace: globalWs.id });
|
|
652
|
+
globalMems = await globalClient.list({ limit: 8 }).catch(() => []);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
catch { /* ignore */ }
|
|
639
656
|
const lines = [];
|
|
640
657
|
lines.push('<stitch-context>');
|
|
641
|
-
lines.push(`Project: ${threadName} · Workspace: ${currentWs?.name || '(unknown)'} · Stitch MCP tools: recall, remember, thread_recall, thread_append, workspace_setup, file_summary, file_summary_save.`);
|
|
658
|
+
lines.push(`Project: ${threadName} · Workspace: ${currentWs?.name || '(unknown)'} · Stitch MCP tools: recall, remember, recall_global, remember_global, thread_recall, thread_append, workspace_setup, file_summary, file_summary_save.`);
|
|
642
659
|
lines.push('');
|
|
643
660
|
// Nudge the AI to set a meaningful workspace name once.
|
|
644
661
|
if (currentWs?.name === 'default') {
|
|
@@ -646,6 +663,15 @@ async function cmdHook(args) {
|
|
|
646
663
|
lines.push('Call the `workspace_setup` MCP tool with a slug-style name based on this project (e.g. the package.json name or repo dir).');
|
|
647
664
|
lines.push('');
|
|
648
665
|
}
|
|
666
|
+
// Global preferences first — they should bias everything else.
|
|
667
|
+
if (globalMems.length > 0) {
|
|
668
|
+
lines.push('### User-level rules & preferences (apply across all projects)');
|
|
669
|
+
for (const m of globalMems) {
|
|
670
|
+
const txt = String(m.content || '').replace(/\n+/g, ' ').slice(0, 350);
|
|
671
|
+
lines.push(`- **[${m.kind}]** ${txt}`);
|
|
672
|
+
}
|
|
673
|
+
lines.push('');
|
|
674
|
+
}
|
|
649
675
|
if (Array.isArray(aboutMems) && aboutMems.length > 0) {
|
|
650
676
|
lines.push('### About this workspace');
|
|
651
677
|
lines.push(String(aboutMems[0].content || '').slice(0, 400));
|
|
@@ -657,7 +683,13 @@ async function cmdHook(args) {
|
|
|
657
683
|
for (const m of sortedMems) {
|
|
658
684
|
const isAuto = Array.isArray(m.tags) && m.tags.includes('auto');
|
|
659
685
|
const txt = String(m.content || '').replace(/\n+/g, ' ').slice(0, 350);
|
|
660
|
-
|
|
686
|
+
// Source receipt: when this memory came from a distilled thread,
|
|
687
|
+
// mark the source so the agent knows it can call thread_recall on
|
|
688
|
+
// that thread for verbatim context behind the fact.
|
|
689
|
+
const src = m.source_thread_id
|
|
690
|
+
? ` _(from thread, ${m.source_turn_ids?.length || 0} turns)_`
|
|
691
|
+
: '';
|
|
692
|
+
lines.push(`- **[${m.kind}${isAuto ? '·auto' : ''}]** ${txt}${src}`);
|
|
661
693
|
}
|
|
662
694
|
lines.push('');
|
|
663
695
|
}
|
|
@@ -679,7 +711,7 @@ async function cmdHook(args) {
|
|
|
679
711
|
}
|
|
680
712
|
lines.push('');
|
|
681
713
|
}
|
|
682
|
-
lines.push('Call `recall` for
|
|
714
|
+
lines.push('Call `recall` for project memory, `recall_global` for cross-project user prefs, `thread_recall` for older turns, `file_summary` BEFORE reading any non-trivial file. Save user-level habits/preferences with `remember_global`; project facts with `remember`.');
|
|
683
715
|
lines.push('</stitch-context>');
|
|
684
716
|
process.stdout.write(lines.join('\n'));
|
|
685
717
|
}
|
|
@@ -1054,7 +1086,6 @@ async function cmdSummarizeFile(args) {
|
|
|
1054
1086
|
return;
|
|
1055
1087
|
try {
|
|
1056
1088
|
const stitch = client(cfg);
|
|
1057
|
-
const projectTag = (inferThread() || 'default').split('/')[0];
|
|
1058
1089
|
// Replace any prior summary for this path.
|
|
1059
1090
|
const prior = await stitch.list({ tag: `file:${rel}`, limit: 50 }).catch(() => []);
|
|
1060
1091
|
for (const p of prior) {
|
|
@@ -1063,9 +1094,13 @@ async function cmdSummarizeFile(args) {
|
|
|
1063
1094
|
}
|
|
1064
1095
|
catch { }
|
|
1065
1096
|
}
|
|
1097
|
+
// No project:* tag — the workspace itself is the project identity now.
|
|
1098
|
+
// Adding a project tag based on inferThread() is the bug that caused
|
|
1099
|
+
// cross-workspace contamination when the workspace pin and the thread
|
|
1100
|
+
// pin disagreed.
|
|
1066
1101
|
await stitch.remember(summary, {
|
|
1067
1102
|
kind: 'snippet',
|
|
1068
|
-
tags: [`file:${rel}`, `hash:${hashPrefix}`, 'auto:file-summary'
|
|
1103
|
+
tags: [`file:${rel}`, `hash:${hashPrefix}`, 'auto:file-summary'],
|
|
1069
1104
|
});
|
|
1070
1105
|
}
|
|
1071
1106
|
catch { /* silent — never break a session */ }
|
|
@@ -1209,13 +1244,25 @@ async function cmdDistill(args) {
|
|
|
1209
1244
|
bumpDistillCooldown(thread);
|
|
1210
1245
|
return;
|
|
1211
1246
|
}
|
|
1212
|
-
// Push each to Stitch as a memory with auto:true tag
|
|
1213
|
-
|
|
1247
|
+
// Push each to Stitch as a memory with auto:true tag, plus receipts:
|
|
1248
|
+
// the source thread + the IDs of the turns this distill batch covered,
|
|
1249
|
+
// and a short excerpt from the most recent user turn so the dashboard /
|
|
1250
|
+
// recall surface can preview the conversational context behind the fact
|
|
1251
|
+
// without an extra round-trip.
|
|
1252
|
+
const sourceTurnIds = recall.recent.map((t) => t.id);
|
|
1253
|
+
const lastUserTurn = [...recall.recent].reverse().find((t) => t.role === 'user');
|
|
1254
|
+
const sourceExcerpt = lastUserTurn ? String(lastUserTurn.content || '').slice(0, 300) : undefined;
|
|
1214
1255
|
let saved = 0;
|
|
1215
1256
|
for (const m of memories) {
|
|
1216
1257
|
try {
|
|
1217
|
-
const tags = ['auto', 'auto:distill', `thread:${thread}`,
|
|
1218
|
-
await stitch.remember(m.content, {
|
|
1258
|
+
const tags = ['auto', 'auto:distill', `thread:${thread}`, ...(m.tags || [])];
|
|
1259
|
+
await stitch.remember(m.content, {
|
|
1260
|
+
kind: m.kind,
|
|
1261
|
+
tags,
|
|
1262
|
+
source_thread_id: recall.thread_id,
|
|
1263
|
+
source_turn_ids: sourceTurnIds,
|
|
1264
|
+
source_excerpt: sourceExcerpt,
|
|
1265
|
+
});
|
|
1219
1266
|
saved++;
|
|
1220
1267
|
}
|
|
1221
1268
|
catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stitchdb/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Stitch CLI — manage memory + run agents from your terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"license": "MIT",
|
|
17
17
|
"engines": { "node": ">=20" },
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@stitchdb/agent": "^0.
|
|
19
|
+
"@stitchdb/agent": "^0.3.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"typescript": "^5.4.0",
|