@stitchdb/cli 0.9.0 → 0.10.1
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 +53 -9
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -629,13 +629,28 @@ async function cmdHook(args) {
|
|
|
629
629
|
const stitch = client(cfg);
|
|
630
630
|
const projectTag = (threadName.split('/')[0] || threadName).toLowerCase();
|
|
631
631
|
const baseUrl = cfg.baseUrl || 'https://db.stitchdb.com';
|
|
632
|
-
|
|
632
|
+
// Adaptive sizing — scale what we inject by how much the project
|
|
633
|
+
// actually has. A 5k-memory pool surfacing 8 random memories is
|
|
634
|
+
// noise; better to inject 0 and tell Claude to `recall` on demand.
|
|
635
|
+
const [thread, allProjectMems, workspaces, fileSummaries, aboutMems] = await Promise.all([
|
|
633
636
|
stitch.thread(threadName).recall({ last: 5 }).catch(() => ({ thread_id: '', recent: [], semantic: [] })),
|
|
634
|
-
stitch.
|
|
637
|
+
stitch.list({ limit: 1 }).catch(() => []), // probe the pool size cheaply
|
|
635
638
|
stitch.workspaces.list().catch(() => []),
|
|
636
639
|
stitch.list({ limit: 12 }).then((all) => all.filter((m) => m.tags.some((t) => t.startsWith('file:')))).catch(() => []),
|
|
637
640
|
stitch.list({ tag: 'workspace:about', limit: 1 }).catch(() => []),
|
|
638
641
|
]);
|
|
642
|
+
// Estimate the workspace's total memory count from a single page
|
|
643
|
+
// header. We just need to know "small / medium / huge" — exact
|
|
644
|
+
// count is overkill. (D1 doesn't expose count in list — approximate
|
|
645
|
+
// by listing 200 once and capping.)
|
|
646
|
+
const sample = await stitch.list({ limit: 200 }).catch(() => []);
|
|
647
|
+
const poolSize = Array.isArray(sample) ? sample.length : 0;
|
|
648
|
+
// Tier the injection: tiny / small / medium / huge.
|
|
649
|
+
const memSliceK = poolSize <= 50 ? 8 : poolSize < 500 ? 8 : 0;
|
|
650
|
+
const turnSliceK = (thread.recent?.length ?? 0) < 5 ? 5 : (thread.recent?.length ?? 0) < 100 ? 5 : 2;
|
|
651
|
+
const memHits = memSliceK > 0
|
|
652
|
+
? await stitch.recall(projectTag, { k: memSliceK }).catch(() => [])
|
|
653
|
+
: [];
|
|
639
654
|
// Look up the current workspace using the client's resolved id; fall
|
|
640
655
|
// back to first if resolveWorkspace failed (shouldn't normally).
|
|
641
656
|
const currentWsId = await stitch.resolveWorkspace().catch(() => null);
|
|
@@ -655,8 +670,15 @@ async function cmdHook(args) {
|
|
|
655
670
|
catch { /* ignore */ }
|
|
656
671
|
const lines = [];
|
|
657
672
|
lines.push('<stitch-context>');
|
|
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.`);
|
|
673
|
+
lines.push(`Project: ${threadName} · Workspace: ${currentWs?.name || '(unknown)'} · ${poolSize} memories indexed · Stitch MCP tools: recall, remember, recall_global, remember_global, thread_recall, thread_append, workspace_setup, file_summary, file_summary_save.`);
|
|
659
674
|
lines.push('');
|
|
675
|
+
// Huge-pool mode: don't pre-load any memories. Tell Claude what's
|
|
676
|
+
// available and that it should pull what's relevant on demand.
|
|
677
|
+
if (poolSize >= 200 && memHits.length === 0) {
|
|
678
|
+
lines.push('### Memory pool');
|
|
679
|
+
lines.push(`This project has ${poolSize}+ memories. Don't try to load them all — call \`recall(query)\` whenever the user references prior decisions, code patterns, or preferences. Cheaper and more relevant than reading them upfront.`);
|
|
680
|
+
lines.push('');
|
|
681
|
+
}
|
|
660
682
|
// Nudge the AI to set a meaningful workspace name once.
|
|
661
683
|
if (currentWs?.name === 'default') {
|
|
662
684
|
lines.push('### ⚠ Workspace is still named "default"');
|
|
@@ -683,7 +705,13 @@ async function cmdHook(args) {
|
|
|
683
705
|
for (const m of sortedMems) {
|
|
684
706
|
const isAuto = Array.isArray(m.tags) && m.tags.includes('auto');
|
|
685
707
|
const txt = String(m.content || '').replace(/\n+/g, ' ').slice(0, 350);
|
|
686
|
-
|
|
708
|
+
// Source receipt: when this memory came from a distilled thread,
|
|
709
|
+
// mark the source so the agent knows it can call thread_recall on
|
|
710
|
+
// that thread for verbatim context behind the fact.
|
|
711
|
+
const src = m.source_thread_id
|
|
712
|
+
? ` _(from thread, ${m.source_turn_ids?.length || 0} turns)_`
|
|
713
|
+
: '';
|
|
714
|
+
lines.push(`- **[${m.kind}${isAuto ? '·auto' : ''}]** ${txt}${src}`);
|
|
687
715
|
}
|
|
688
716
|
lines.push('');
|
|
689
717
|
}
|
|
@@ -699,13 +727,17 @@ async function cmdHook(args) {
|
|
|
699
727
|
}
|
|
700
728
|
if (thread.recent && thread.recent.length > 0) {
|
|
701
729
|
lines.push('### Most recent turns (continue from here)');
|
|
702
|
-
for (const t of thread.recent.slice(-
|
|
730
|
+
for (const t of thread.recent.slice(-turnSliceK)) {
|
|
703
731
|
const txt = String(t.content || '').replace(/\n+/g, ' ').slice(0, 300);
|
|
704
732
|
lines.push(`- **${t.role}**: ${txt}`);
|
|
705
733
|
}
|
|
706
734
|
lines.push('');
|
|
707
735
|
}
|
|
708
|
-
lines.push('
|
|
736
|
+
lines.push('## How to use this memory layer');
|
|
737
|
+
lines.push('- The user mentions prior work, decisions, or "what we discussed" → call `recall(query)` (or `thread_recall(thread, semantic: ...)` for verbatim turns) BEFORE answering. Don\'t guess from the snippets above; they\'re a teaser, not the truth.');
|
|
738
|
+
lines.push('- About to open a non-trivial file → call `file_summary(path)` first. If hash matches the cached summary, you can skip the full read entirely.');
|
|
739
|
+
lines.push('- Learn a durable user-level habit ("I always use Postgres", "commit before reverting") → save with `remember_global` so it surfaces across every project. Project-specific facts → `remember`.');
|
|
740
|
+
lines.push('- A surfaced memory has `_(from thread, N turns)_` next to it → those turns are queryable via `thread_recall`. Reach for them when challenged on a fact.');
|
|
709
741
|
lines.push('</stitch-context>');
|
|
710
742
|
process.stdout.write(lines.join('\n'));
|
|
711
743
|
}
|
|
@@ -1238,13 +1270,25 @@ async function cmdDistill(args) {
|
|
|
1238
1270
|
bumpDistillCooldown(thread);
|
|
1239
1271
|
return;
|
|
1240
1272
|
}
|
|
1241
|
-
// Push each to Stitch as a memory with auto:true tag
|
|
1242
|
-
// the
|
|
1273
|
+
// Push each to Stitch as a memory with auto:true tag, plus receipts:
|
|
1274
|
+
// the source thread + the IDs of the turns this distill batch covered,
|
|
1275
|
+
// and a short excerpt from the most recent user turn so the dashboard /
|
|
1276
|
+
// recall surface can preview the conversational context behind the fact
|
|
1277
|
+
// without an extra round-trip.
|
|
1278
|
+
const sourceTurnIds = recall.recent.map((t) => t.id);
|
|
1279
|
+
const lastUserTurn = [...recall.recent].reverse().find((t) => t.role === 'user');
|
|
1280
|
+
const sourceExcerpt = lastUserTurn ? String(lastUserTurn.content || '').slice(0, 300) : undefined;
|
|
1243
1281
|
let saved = 0;
|
|
1244
1282
|
for (const m of memories) {
|
|
1245
1283
|
try {
|
|
1246
1284
|
const tags = ['auto', 'auto:distill', `thread:${thread}`, ...(m.tags || [])];
|
|
1247
|
-
await stitch.remember(m.content, {
|
|
1285
|
+
await stitch.remember(m.content, {
|
|
1286
|
+
kind: m.kind,
|
|
1287
|
+
tags,
|
|
1288
|
+
source_thread_id: recall.thread_id,
|
|
1289
|
+
source_turn_ids: sourceTurnIds,
|
|
1290
|
+
source_excerpt: sourceExcerpt,
|
|
1291
|
+
});
|
|
1248
1292
|
saved++;
|
|
1249
1293
|
}
|
|
1250
1294
|
catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stitchdb/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
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",
|