open-think 0.1.5 → 0.1.7
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/index.js +98 -61
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13,8 +13,8 @@ import { v7 as uuidv7 } from "uuid";
|
|
|
13
13
|
import { startOfWeek, endOfWeek, subWeeks } from "date-fns";
|
|
14
14
|
|
|
15
15
|
// src/db/client.ts
|
|
16
|
-
import
|
|
17
|
-
import
|
|
16
|
+
import path2 from "path";
|
|
17
|
+
import fs2 from "fs";
|
|
18
18
|
import { DatabaseSync } from "node:sqlite";
|
|
19
19
|
|
|
20
20
|
// src/db/schema.ts
|
|
@@ -44,17 +44,75 @@ function ensureSchema(db2) {
|
|
|
44
44
|
`);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
// src/lib/paths.ts
|
|
48
|
+
import path from "path";
|
|
49
|
+
import fs from "fs";
|
|
50
|
+
function getHome() {
|
|
51
|
+
const home = process.env.HOME;
|
|
52
|
+
if (!home) {
|
|
53
|
+
throw new Error("HOME environment variable is not set");
|
|
54
|
+
}
|
|
55
|
+
return home;
|
|
56
|
+
}
|
|
57
|
+
function sanitizeName(name) {
|
|
58
|
+
if (!name || /[\/\\\.]{2}/.test(name) || /[^a-zA-Z0-9_-]/.test(name)) {
|
|
59
|
+
throw new Error(`Invalid cortex name: "${name}". Use only alphanumeric characters, hyphens, and underscores.`);
|
|
60
|
+
}
|
|
61
|
+
return name;
|
|
62
|
+
}
|
|
63
|
+
function getThinkHome() {
|
|
64
|
+
const thinkHome = process.env.THINK_HOME;
|
|
65
|
+
if (thinkHome === void 0 || thinkHome === "") return null;
|
|
66
|
+
return thinkHome;
|
|
67
|
+
}
|
|
68
|
+
function getThinkDir() {
|
|
69
|
+
return getThinkHome() ?? path.join(getHome(), ".think");
|
|
70
|
+
}
|
|
71
|
+
function getThinkConfigDir() {
|
|
72
|
+
const thinkHome = getThinkHome();
|
|
73
|
+
if (thinkHome) return path.join(thinkHome, "config");
|
|
74
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME || path.join(getHome(), ".config");
|
|
75
|
+
return path.join(xdgConfig, "think");
|
|
76
|
+
}
|
|
77
|
+
function getThinkDataDir() {
|
|
78
|
+
const thinkHome = getThinkHome();
|
|
79
|
+
if (thinkHome) return path.join(thinkHome, "data");
|
|
80
|
+
const xdgData = process.env.XDG_DATA_HOME || path.join(getHome(), ".local", "share");
|
|
81
|
+
return path.join(xdgData, "think");
|
|
82
|
+
}
|
|
83
|
+
function getEngramsDir() {
|
|
84
|
+
return path.join(getThinkDir(), "engrams");
|
|
85
|
+
}
|
|
86
|
+
function getEngramDbPath(cortexName) {
|
|
87
|
+
return path.join(getEngramsDir(), `${sanitizeName(cortexName)}.db`);
|
|
88
|
+
}
|
|
89
|
+
function getRepoPath() {
|
|
90
|
+
return path.join(getThinkDir(), "repo");
|
|
91
|
+
}
|
|
92
|
+
function getLongtermDir() {
|
|
93
|
+
return path.join(getThinkDir(), "longterm");
|
|
94
|
+
}
|
|
95
|
+
function getLongtermPath(cortexName) {
|
|
96
|
+
return path.join(getLongtermDir(), `${sanitizeName(cortexName)}.md`);
|
|
97
|
+
}
|
|
98
|
+
function getCuratorMdPath() {
|
|
99
|
+
return path.join(getThinkDir(), "curator.md");
|
|
100
|
+
}
|
|
101
|
+
function ensureThinkDirs() {
|
|
102
|
+
fs.mkdirSync(getEngramsDir(), { recursive: true });
|
|
103
|
+
fs.mkdirSync(getLongtermDir(), { recursive: true });
|
|
104
|
+
}
|
|
105
|
+
|
|
47
106
|
// src/db/client.ts
|
|
48
107
|
var db = null;
|
|
49
108
|
function getDataDir() {
|
|
50
|
-
|
|
51
|
-
return path.join(xdgData, "think");
|
|
109
|
+
return getThinkDataDir();
|
|
52
110
|
}
|
|
53
111
|
function getDb() {
|
|
54
112
|
if (db) return db;
|
|
55
113
|
const dataDir = getDataDir();
|
|
56
|
-
|
|
57
|
-
const dbPath =
|
|
114
|
+
fs2.mkdirSync(dataDir, { recursive: true });
|
|
115
|
+
const dbPath = path2.join(dataDir, "think.db");
|
|
58
116
|
db = new DatabaseSync(dbPath);
|
|
59
117
|
db.exec("PRAGMA journal_mode = WAL");
|
|
60
118
|
db.exec("PRAGMA synchronous = NORMAL");
|
|
@@ -131,25 +189,24 @@ function deleteEntriesByContent(pattern) {
|
|
|
131
189
|
}
|
|
132
190
|
|
|
133
191
|
// src/lib/config.ts
|
|
134
|
-
import
|
|
135
|
-
import
|
|
192
|
+
import path3 from "path";
|
|
193
|
+
import fs3 from "fs";
|
|
136
194
|
import { v4 as uuidv4 } from "uuid";
|
|
137
195
|
function getConfigDir() {
|
|
138
|
-
|
|
139
|
-
return path2.join(xdgConfig, "think");
|
|
196
|
+
return getThinkConfigDir();
|
|
140
197
|
}
|
|
141
198
|
function configPath() {
|
|
142
|
-
return
|
|
199
|
+
return path3.join(getConfigDir(), "config.json");
|
|
143
200
|
}
|
|
144
201
|
function saveConfig(config) {
|
|
145
202
|
const dir = getConfigDir();
|
|
146
|
-
|
|
147
|
-
|
|
203
|
+
fs3.mkdirSync(dir, { recursive: true });
|
|
204
|
+
fs3.writeFileSync(configPath(), JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
148
205
|
}
|
|
149
206
|
function getConfig() {
|
|
150
207
|
const fp = configPath();
|
|
151
|
-
if (
|
|
152
|
-
const raw =
|
|
208
|
+
if (fs3.existsSync(fp)) {
|
|
209
|
+
const raw = fs3.readFileSync(fp, "utf-8");
|
|
153
210
|
return JSON.parse(raw);
|
|
154
211
|
}
|
|
155
212
|
const config = {
|
|
@@ -165,50 +222,6 @@ import { v7 as uuidv72 } from "uuid";
|
|
|
165
222
|
|
|
166
223
|
// src/db/engrams.ts
|
|
167
224
|
import { DatabaseSync as DatabaseSync2 } from "node:sqlite";
|
|
168
|
-
|
|
169
|
-
// src/lib/paths.ts
|
|
170
|
-
import path3 from "path";
|
|
171
|
-
import fs3 from "fs";
|
|
172
|
-
function getHome() {
|
|
173
|
-
const home = process.env.HOME;
|
|
174
|
-
if (!home) {
|
|
175
|
-
throw new Error("HOME environment variable is not set");
|
|
176
|
-
}
|
|
177
|
-
return home;
|
|
178
|
-
}
|
|
179
|
-
function sanitizeName(name) {
|
|
180
|
-
if (!name || /[\/\\\.]{2}/.test(name) || /[^a-zA-Z0-9_-]/.test(name)) {
|
|
181
|
-
throw new Error(`Invalid cortex name: "${name}". Use only alphanumeric characters, hyphens, and underscores.`);
|
|
182
|
-
}
|
|
183
|
-
return name;
|
|
184
|
-
}
|
|
185
|
-
function getThinkDir() {
|
|
186
|
-
return path3.join(getHome(), ".think");
|
|
187
|
-
}
|
|
188
|
-
function getEngramsDir() {
|
|
189
|
-
return path3.join(getThinkDir(), "engrams");
|
|
190
|
-
}
|
|
191
|
-
function getEngramDbPath(cortexName) {
|
|
192
|
-
return path3.join(getEngramsDir(), `${sanitizeName(cortexName)}.db`);
|
|
193
|
-
}
|
|
194
|
-
function getRepoPath() {
|
|
195
|
-
return path3.join(getThinkDir(), "repo");
|
|
196
|
-
}
|
|
197
|
-
function getLongtermDir() {
|
|
198
|
-
return path3.join(getThinkDir(), "longterm");
|
|
199
|
-
}
|
|
200
|
-
function getLongtermPath(cortexName) {
|
|
201
|
-
return path3.join(getLongtermDir(), `${sanitizeName(cortexName)}.md`);
|
|
202
|
-
}
|
|
203
|
-
function getCuratorMdPath() {
|
|
204
|
-
return path3.join(getThinkDir(), "curator.md");
|
|
205
|
-
}
|
|
206
|
-
function ensureThinkDirs() {
|
|
207
|
-
fs3.mkdirSync(getEngramsDir(), { recursive: true });
|
|
208
|
-
fs3.mkdirSync(getLongtermDir(), { recursive: true });
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// src/db/engrams.ts
|
|
212
225
|
var dbs = /* @__PURE__ */ new Map();
|
|
213
226
|
function ensureEngramSchema(db2) {
|
|
214
227
|
db2.exec(`
|
|
@@ -1169,7 +1182,25 @@ function assembleCurationPrompt(params) {
|
|
|
1169
1182
|
const memoriesText = params.existingMemories.length > 0 ? params.existingMemories.map((m) => `- [${m.ts}] ${m.author}: ${m.content}`).join("\n") : "(no memories yet)";
|
|
1170
1183
|
const curatorMdText = params.curatorMd ?? "(none provided)";
|
|
1171
1184
|
const engramsText = params.pendingEngrams.map((e) => `- [${e.created_at}] (id: ${e.id}) ${e.content}`).join("\n");
|
|
1172
|
-
|
|
1185
|
+
let prompt3 = BASE_CURATION_PROMPT.replace("{existing_memories}", memoriesText).replace("{curator_md}", curatorMdText).replace("{pending_engrams}", engramsText);
|
|
1186
|
+
const tuning = [];
|
|
1187
|
+
if (params.selectivity === "high") {
|
|
1188
|
+
tuning.push("Be very selective. Only promote clearly significant events: major decisions, shipped deliverables, critical blockers, direction changes. Skip routine commits, minor fixes, and incremental progress.");
|
|
1189
|
+
} else if (params.selectivity === "low") {
|
|
1190
|
+
tuning.push("Be inclusive. Promote most work events that have any team relevance. Only drop purely administrative or personal events.");
|
|
1191
|
+
}
|
|
1192
|
+
if (params.granularity === "summary") {
|
|
1193
|
+
tuning.push("Consolidate related events into single memory entries. Prefer fewer, broader memories over many specific ones.");
|
|
1194
|
+
} else if (params.granularity === "detailed") {
|
|
1195
|
+
tuning.push("Keep memories specific and granular. Each distinct event or decision should be its own memory entry. Do not roll up multiple events into one.");
|
|
1196
|
+
}
|
|
1197
|
+
if (params.maxMemoriesPerRun && params.maxMemoriesPerRun > 0) {
|
|
1198
|
+
tuning.push(`Produce at most ${params.maxMemoriesPerRun} memory entries from this batch. If more events are significant, prioritize the most important.`);
|
|
1199
|
+
}
|
|
1200
|
+
if (tuning.length > 0) {
|
|
1201
|
+
prompt3 += "\n\nAdditional instructions:\n" + tuning.map((t) => `- ${t}`).join("\n");
|
|
1202
|
+
}
|
|
1203
|
+
return prompt3;
|
|
1173
1204
|
}
|
|
1174
1205
|
function parseMemoriesJsonl(content) {
|
|
1175
1206
|
if (!content.trim()) return [];
|
|
@@ -1264,7 +1295,10 @@ var curateCommand = new Command10("curate").description("Run curation: evaluate
|
|
|
1264
1295
|
existingMemories,
|
|
1265
1296
|
curatorMd,
|
|
1266
1297
|
pendingEngrams: pending,
|
|
1267
|
-
author
|
|
1298
|
+
author,
|
|
1299
|
+
selectivity: config.cortex?.selectivity,
|
|
1300
|
+
granularity: config.cortex?.granularity,
|
|
1301
|
+
maxMemoriesPerRun: config.cortex?.maxMemoriesPerRun
|
|
1268
1302
|
});
|
|
1269
1303
|
let newEntries;
|
|
1270
1304
|
try {
|
|
@@ -1589,6 +1623,9 @@ import chalk17 from "chalk";
|
|
|
1589
1623
|
var ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
1590
1624
|
"cortex.curateEveryN",
|
|
1591
1625
|
"cortex.confirmBeforeCommit",
|
|
1626
|
+
"cortex.selectivity",
|
|
1627
|
+
"cortex.granularity",
|
|
1628
|
+
"cortex.maxMemoriesPerRun",
|
|
1592
1629
|
"cortex.author",
|
|
1593
1630
|
"cortex.repo",
|
|
1594
1631
|
"cortex.active",
|