deepthinking-mcp 2.5.2 → 2.5.4

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 CHANGED
@@ -991,8 +991,218 @@ var ModeRecommender = class {
991
991
  }
992
992
  };
993
993
 
994
- // src/session/manager.ts
994
+ // src/utils/errors.ts
995
+ var DeepThinkingError = class extends Error {
996
+ code;
997
+ context;
998
+ timestamp;
999
+ constructor(message, code, context) {
1000
+ super(message);
1001
+ this.name = this.constructor.name;
1002
+ this.code = code;
1003
+ this.context = context;
1004
+ this.timestamp = /* @__PURE__ */ new Date();
1005
+ if (Error.captureStackTrace) {
1006
+ Error.captureStackTrace(this, this.constructor);
1007
+ }
1008
+ }
1009
+ /**
1010
+ * Convert error to JSON for logging/serialization
1011
+ */
1012
+ toJSON() {
1013
+ return {
1014
+ name: this.name,
1015
+ message: this.message,
1016
+ code: this.code,
1017
+ context: this.context,
1018
+ timestamp: this.timestamp.toISOString(),
1019
+ stack: this.stack
1020
+ };
1021
+ }
1022
+ };
1023
+ var SessionError = class extends DeepThinkingError {
1024
+ constructor(message, context) {
1025
+ super(message, "SESSION_ERROR", context);
1026
+ }
1027
+ };
1028
+ var SessionNotFoundError = class extends SessionError {
1029
+ constructor(sessionId) {
1030
+ super(`Session not found: ${sessionId}`, { sessionId });
1031
+ this.code = "SESSION_NOT_FOUND";
1032
+ }
1033
+ };
1034
+
1035
+ // src/utils/sanitization.ts
1036
+ var MAX_LENGTHS = {
1037
+ THOUGHT_CONTENT: 1e5,
1038
+ // 100KB for thought content
1039
+ TITLE: 500,
1040
+ DOMAIN: 200,
1041
+ AUTHOR: 300,
1042
+ STRING_FIELD: 1e3
1043
+ };
1044
+ function sanitizeString(input, maxLength = MAX_LENGTHS.STRING_FIELD, fieldName = "input") {
1045
+ if (typeof input !== "string") {
1046
+ throw new Error(`${fieldName} must be a string`);
1047
+ }
1048
+ const trimmed = input.trim();
1049
+ if (trimmed.length === 0) {
1050
+ throw new Error(`${fieldName} cannot be empty`);
1051
+ }
1052
+ if (trimmed.length > maxLength) {
1053
+ throw new Error(`${fieldName} exceeds maximum length of ${maxLength} characters`);
1054
+ }
1055
+ if (trimmed.includes("\0")) {
1056
+ throw new Error(`${fieldName} contains invalid null bytes`);
1057
+ }
1058
+ return trimmed;
1059
+ }
1060
+ function validateSessionId(sessionId) {
1061
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1062
+ if (!uuidRegex.test(sessionId)) {
1063
+ throw new Error(`Invalid session ID format: ${sessionId}`);
1064
+ }
1065
+ return sessionId;
1066
+ }
1067
+ function sanitizeThoughtContent(content) {
1068
+ return sanitizeString(content, MAX_LENGTHS.THOUGHT_CONTENT, "thought content");
1069
+ }
1070
+
1071
+ // src/utils/logger.ts
1072
+ var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
1073
+ LogLevel2[LogLevel2["DEBUG"] = 0] = "DEBUG";
1074
+ LogLevel2[LogLevel2["INFO"] = 1] = "INFO";
1075
+ LogLevel2[LogLevel2["WARN"] = 2] = "WARN";
1076
+ LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
1077
+ LogLevel2[LogLevel2["SILENT"] = 4] = "SILENT";
1078
+ return LogLevel2;
1079
+ })(LogLevel || {});
995
1080
  var DEFAULT_CONFIG = {
1081
+ minLevel: 1 /* INFO */,
1082
+ enableConsole: true,
1083
+ enableTimestamps: true,
1084
+ prettyPrint: true
1085
+ };
1086
+ var Logger = class {
1087
+ config;
1088
+ logs = [];
1089
+ constructor(config) {
1090
+ this.config = { ...DEFAULT_CONFIG, ...config };
1091
+ }
1092
+ /**
1093
+ * Log a debug message
1094
+ */
1095
+ debug(message, context) {
1096
+ this.log(0 /* DEBUG */, message, context);
1097
+ }
1098
+ /**
1099
+ * Log an info message
1100
+ */
1101
+ info(message, context) {
1102
+ this.log(1 /* INFO */, message, context);
1103
+ }
1104
+ /**
1105
+ * Log a warning message
1106
+ */
1107
+ warn(message, context) {
1108
+ this.log(2 /* WARN */, message, context);
1109
+ }
1110
+ /**
1111
+ * Log an error message
1112
+ */
1113
+ error(message, error, context) {
1114
+ this.log(3 /* ERROR */, message, context, error);
1115
+ }
1116
+ /**
1117
+ * Internal log method
1118
+ */
1119
+ log(level, message, context, error) {
1120
+ if (level < this.config.minLevel) {
1121
+ return;
1122
+ }
1123
+ const entry = {
1124
+ level,
1125
+ message,
1126
+ timestamp: /* @__PURE__ */ new Date(),
1127
+ context,
1128
+ error
1129
+ };
1130
+ this.logs.push(entry);
1131
+ if (this.config.enableConsole) {
1132
+ this.writeToConsole(entry);
1133
+ }
1134
+ }
1135
+ /**
1136
+ * Write log entry to console
1137
+ */
1138
+ writeToConsole(entry) {
1139
+ const levelName = LogLevel[entry.level];
1140
+ const timestamp = this.config.enableTimestamps ? `[${entry.timestamp.toISOString()}] ` : "";
1141
+ let message = `${timestamp}${levelName}: ${entry.message}`;
1142
+ if (entry.context && this.config.prettyPrint) {
1143
+ message += `
1144
+ Context: ${JSON.stringify(entry.context, null, 2)}`;
1145
+ }
1146
+ if (entry.error) {
1147
+ message += `
1148
+ Error: ${entry.error.message}`;
1149
+ if (entry.error.stack && this.config.prettyPrint) {
1150
+ message += `
1151
+ Stack: ${entry.error.stack}`;
1152
+ }
1153
+ }
1154
+ switch (entry.level) {
1155
+ case 0 /* DEBUG */:
1156
+ case 1 /* INFO */:
1157
+ console.log(message);
1158
+ break;
1159
+ case 2 /* WARN */:
1160
+ console.warn(message);
1161
+ break;
1162
+ case 3 /* ERROR */:
1163
+ console.error(message);
1164
+ break;
1165
+ }
1166
+ }
1167
+ /**
1168
+ * Get all log entries
1169
+ */
1170
+ getLogs(minLevel) {
1171
+ if (minLevel !== void 0) {
1172
+ return this.logs.filter((log) => log.level >= minLevel);
1173
+ }
1174
+ return [...this.logs];
1175
+ }
1176
+ /**
1177
+ * Clear all logs
1178
+ */
1179
+ clearLogs() {
1180
+ this.logs = [];
1181
+ }
1182
+ /**
1183
+ * Set minimum log level
1184
+ */
1185
+ setLevel(level) {
1186
+ this.config.minLevel = level;
1187
+ }
1188
+ /**
1189
+ * Export logs as JSON
1190
+ */
1191
+ exportLogs() {
1192
+ return JSON.stringify(this.logs.map((log) => ({
1193
+ ...log,
1194
+ level: LogLevel[log.level],
1195
+ timestamp: log.timestamp.toISOString()
1196
+ })), null, 2);
1197
+ }
1198
+ };
1199
+ new Logger();
1200
+ function createLogger(config) {
1201
+ return new Logger(config);
1202
+ }
1203
+
1204
+ // src/session/manager.ts
1205
+ var DEFAULT_CONFIG2 = {
996
1206
  modeConfig: {
997
1207
  mode: "hybrid" /* HYBRID */,
998
1208
  strictValidation: false,
@@ -1010,48 +1220,139 @@ var DEFAULT_CONFIG = {
1010
1220
  var SessionManager = class {
1011
1221
  activeSessions;
1012
1222
  config;
1013
- constructor(config) {
1223
+ logger;
1224
+ /**
1225
+ * Creates a new SessionManager instance
1226
+ *
1227
+ * @param config - Optional default configuration applied to all new sessions
1228
+ * @param logLevel - Optional minimum log level (default: INFO)
1229
+ *
1230
+ * @example
1231
+ * ```typescript
1232
+ * const manager = new SessionManager({
1233
+ * enableAutoSave: true,
1234
+ * maxThoughtsInMemory: 500
1235
+ * }, LogLevel.DEBUG);
1236
+ * ```
1237
+ */
1238
+ constructor(config, logLevel) {
1014
1239
  this.activeSessions = /* @__PURE__ */ new Map();
1015
1240
  this.config = config || {};
1241
+ this.logger = createLogger({
1242
+ minLevel: logLevel || 1 /* INFO */,
1243
+ enableConsole: true
1244
+ });
1016
1245
  }
1017
1246
  /**
1018
1247
  * Create a new thinking session
1248
+ *
1249
+ * Creates and initializes a new thinking session with the specified configuration.
1250
+ * Sessions are stored in memory and tracked until explicitly deleted.
1251
+ *
1252
+ * @param options - Session creation options
1253
+ * @param options.title - Session title (default: 'Untitled Session')
1254
+ * @param options.mode - Thinking mode to use (default: HYBRID)
1255
+ * @param options.domain - Problem domain (e.g., 'mathematics', 'physics')
1256
+ * @param options.author - Session creator/author
1257
+ * @param options.config - Session-specific configuration overrides
1258
+ * @returns Promise resolving to the created session
1259
+ *
1260
+ * @example
1261
+ * ```typescript
1262
+ * const session = await manager.createSession({
1263
+ * title: 'Mathematical Proof',
1264
+ * mode: ThinkingMode.MATHEMATICS,
1265
+ * domain: 'number-theory',
1266
+ * author: 'user@example.com'
1267
+ * });
1268
+ * ```
1019
1269
  */
1020
1270
  async createSession(options = {}) {
1271
+ const title = options.title ? sanitizeString(options.title, MAX_LENGTHS.TITLE, "title") : "Untitled Session";
1272
+ const domain = options.domain ? sanitizeString(options.domain, MAX_LENGTHS.DOMAIN, "domain") : void 0;
1273
+ const author = options.author ? sanitizeString(options.author, MAX_LENGTHS.AUTHOR, "author") : void 0;
1021
1274
  const sessionId = randomUUID();
1022
1275
  const now = /* @__PURE__ */ new Date();
1023
1276
  const session = {
1024
1277
  id: sessionId,
1025
- title: options.title || "Untitled Session",
1278
+ title,
1026
1279
  mode: options.mode || "hybrid" /* HYBRID */,
1027
- domain: options.domain,
1280
+ domain,
1028
1281
  config: this.mergeConfig(options.config),
1029
1282
  thoughts: [],
1030
1283
  createdAt: now,
1031
1284
  updatedAt: now,
1032
- author: options.author,
1285
+ author,
1033
1286
  currentThoughtNumber: 0,
1034
1287
  isComplete: false,
1035
1288
  metrics: this.initializeMetrics(),
1036
1289
  tags: [],
1037
- collaborators: options.author ? [options.author] : []
1290
+ collaborators: author ? [author] : []
1038
1291
  };
1039
1292
  this.activeSessions.set(sessionId, session);
1293
+ this.logger.info("Session created", {
1294
+ sessionId,
1295
+ title,
1296
+ mode: session.mode,
1297
+ domain,
1298
+ author
1299
+ });
1040
1300
  return session;
1041
1301
  }
1042
1302
  /**
1043
1303
  * Get a session by ID
1304
+ *
1305
+ * Retrieves an active session by its unique identifier.
1306
+ *
1307
+ * @param sessionId - Unique UUID v4 identifier of the session
1308
+ * @returns Promise resolving to the session, or null if not found
1309
+ *
1310
+ * @example
1311
+ * ```typescript
1312
+ * const session = await manager.getSession('550e8400-e29b-41d4-a716-446655440000');
1313
+ * if (session) {
1314
+ * console.log(`Session: ${session.title}`);
1315
+ * console.log(`Thoughts: ${session.thoughts.length}`);
1316
+ * }
1317
+ * ```
1044
1318
  */
1045
1319
  async getSession(sessionId) {
1046
1320
  return this.activeSessions.get(sessionId) || null;
1047
1321
  }
1048
1322
  /**
1049
1323
  * Add a thought to a session
1324
+ *
1325
+ * Adds a new thought to an existing session and automatically updates:
1326
+ * - Session metrics (uses O(1) incremental calculation)
1327
+ * - Thought timestamps
1328
+ * - Session completion status
1329
+ * - Mode-specific analytics
1330
+ *
1331
+ * @param sessionId - ID of the session to add thought to
1332
+ * @param thought - The thought object to add
1333
+ * @returns Promise resolving to the updated session
1334
+ * @throws Error if session is not found
1335
+ *
1336
+ * @example
1337
+ * ```typescript
1338
+ * await manager.addThought(session.id, {
1339
+ * thought: 'Initial hypothesis: the problem can be solved using...',
1340
+ * thoughtNumber: 1,
1341
+ * totalThoughts: 5,
1342
+ * nextThoughtNeeded: true,
1343
+ * uncertainty: 0.3
1344
+ * });
1345
+ * ```
1050
1346
  */
1051
1347
  async addThought(sessionId, thought) {
1348
+ validateSessionId(sessionId);
1052
1349
  const session = this.activeSessions.get(sessionId);
1053
1350
  if (!session) {
1054
- throw new Error(`Session ${sessionId} not found`);
1351
+ this.logger.error("Session not found", void 0, { sessionId });
1352
+ throw new SessionNotFoundError(sessionId);
1353
+ }
1354
+ if (thought.content) {
1355
+ thought.content = sanitizeThoughtContent(thought.content);
1055
1356
  }
1056
1357
  thought.sessionId = sessionId;
1057
1358
  thought.timestamp = /* @__PURE__ */ new Date();
@@ -1061,25 +1362,74 @@ var SessionManager = class {
1061
1362
  this.updateMetrics(session, thought);
1062
1363
  if (!thought.nextThoughtNeeded) {
1063
1364
  session.isComplete = true;
1365
+ this.logger.info("Session completed", {
1366
+ sessionId,
1367
+ title: session.title,
1368
+ totalThoughts: session.thoughts.length
1369
+ });
1064
1370
  }
1371
+ this.logger.debug("Thought added", {
1372
+ sessionId,
1373
+ thoughtNumber: thought.thoughtNumber,
1374
+ totalThoughts: session.thoughts.length
1375
+ });
1065
1376
  return session;
1066
1377
  }
1067
1378
  /**
1068
- * Update session mode
1379
+ * Update session mode (switch reasoning approach mid-session)
1380
+ *
1381
+ * Changes the thinking mode of an active session. This is useful when
1382
+ * the problem requires a different reasoning approach.
1383
+ *
1384
+ * @param sessionId - ID of the session to update
1385
+ * @param newMode - New thinking mode to switch to
1386
+ * @param reason - Optional reason for the mode switch
1387
+ * @returns Promise resolving to the updated session
1388
+ * @throws Error if session is not found
1389
+ *
1390
+ * @example
1391
+ * ```typescript
1392
+ * await manager.switchMode(
1393
+ * session.id,
1394
+ * ThinkingMode.CAUSAL,
1395
+ * 'Need to analyze cause-effect relationships'
1396
+ * );
1397
+ * ```
1069
1398
  */
1070
1399
  async switchMode(sessionId, newMode, reason) {
1400
+ validateSessionId(sessionId);
1071
1401
  const session = this.activeSessions.get(sessionId);
1072
1402
  if (!session) {
1073
- throw new Error(`Session ${sessionId} not found`);
1403
+ this.logger.error("Session not found", void 0, { sessionId });
1404
+ throw new SessionNotFoundError(sessionId);
1074
1405
  }
1075
- session.mode;
1406
+ const oldMode = session.mode;
1076
1407
  session.mode = newMode;
1077
1408
  session.config.modeConfig.mode = newMode;
1078
1409
  session.updatedAt = /* @__PURE__ */ new Date();
1410
+ this.logger.info("Session mode switched", {
1411
+ sessionId,
1412
+ oldMode,
1413
+ newMode,
1414
+ reason
1415
+ });
1079
1416
  return session;
1080
1417
  }
1081
1418
  /**
1082
- * List all sessions
1419
+ * List all active sessions with metadata
1420
+ *
1421
+ * Returns summary information for all sessions currently managed
1422
+ * by this SessionManager instance.
1423
+ *
1424
+ * @returns Promise resolving to array of session metadata
1425
+ *
1426
+ * @example
1427
+ * ```typescript
1428
+ * const sessions = await manager.listSessions();
1429
+ * sessions.forEach(s => {
1430
+ * console.log(`${s.title}: ${s.thoughtCount} thoughts (${s.mode})`);
1431
+ * });
1432
+ * ```
1083
1433
  */
1084
1434
  async listSessions() {
1085
1435
  return Array.from(this.activeSessions.values()).map((session) => ({
@@ -1094,17 +1444,59 @@ var SessionManager = class {
1094
1444
  }
1095
1445
  /**
1096
1446
  * Delete a session
1447
+ *
1448
+ * Removes a session from memory. This operation cannot be undone.
1449
+ *
1450
+ * @param sessionId - ID of the session to delete
1451
+ * @returns Promise that resolves when deletion is complete
1452
+ *
1453
+ * @example
1454
+ * ```typescript
1455
+ * await manager.deleteSession('old-session-id');
1456
+ * ```
1097
1457
  */
1098
1458
  async deleteSession(sessionId) {
1099
- this.activeSessions.delete(sessionId);
1459
+ const session = this.activeSessions.get(sessionId);
1460
+ const deleted = this.activeSessions.delete(sessionId);
1461
+ if (deleted && session) {
1462
+ this.logger.info("Session deleted", {
1463
+ sessionId,
1464
+ title: session.title,
1465
+ thoughtCount: session.thoughts.length
1466
+ });
1467
+ } else {
1468
+ this.logger.warn("Attempted to delete non-existent session", { sessionId });
1469
+ }
1100
1470
  }
1101
1471
  /**
1102
- * Generate summary of session
1472
+ * Generate a text summary of a session
1473
+ *
1474
+ * Creates a markdown-formatted summary including:
1475
+ * - Session metadata (title, mode, status)
1476
+ * - Total thought count
1477
+ * - Key thoughts (first 100 characters of each)
1478
+ *
1479
+ * @param sessionId - ID of the session to summarize
1480
+ * @returns Promise resolving to markdown-formatted summary
1481
+ * @throws Error if session is not found
1482
+ *
1483
+ * @example
1484
+ * ```typescript
1485
+ * const summary = await manager.generateSummary(session.id);
1486
+ * console.log(summary);
1487
+ * // Output:
1488
+ * // # Mathematical Proof
1489
+ * // Mode: mathematics
1490
+ * // Total Thoughts: 15
1491
+ * // Status: Complete
1492
+ * // ...
1493
+ * ```
1103
1494
  */
1104
1495
  async generateSummary(sessionId) {
1496
+ validateSessionId(sessionId);
1105
1497
  const session = this.activeSessions.get(sessionId);
1106
1498
  if (!session) {
1107
- throw new Error(`Session ${sessionId} not found`);
1499
+ throw new SessionNotFoundError(sessionId);
1108
1500
  }
1109
1501
  let summary = `# ${session.title}
1110
1502
 
@@ -1126,17 +1518,22 @@ var SessionManager = class {
1126
1518
  return summary;
1127
1519
  }
1128
1520
  /**
1129
- * Merge configurations
1521
+ * Merge configurations (private helper)
1522
+ *
1523
+ * Combines default config, instance config, and user config
1524
+ * with proper precedence: user > instance > default
1130
1525
  */
1131
1526
  mergeConfig(userConfig) {
1132
1527
  return {
1133
- ...DEFAULT_CONFIG,
1528
+ ...DEFAULT_CONFIG2,
1134
1529
  ...this.config,
1135
1530
  ...userConfig
1136
1531
  };
1137
1532
  }
1138
1533
  /**
1139
- * Initialize metrics
1534
+ * Initialize metrics (private helper)
1535
+ *
1536
+ * Creates a fresh SessionMetrics object with zero values
1140
1537
  */
1141
1538
  initializeMetrics() {
1142
1539
  return {
@@ -1150,7 +1547,13 @@ var SessionManager = class {
1150
1547
  };
1151
1548
  }
1152
1549
  /**
1153
- * Update session metrics
1550
+ * Update session metrics (private helper)
1551
+ *
1552
+ * Incrementally updates metrics using O(1) algorithms for performance.
1553
+ * Handles mode-specific metrics for temporal, game theory, and evidential modes.
1554
+ *
1555
+ * @param session - Session to update
1556
+ * @param thought - Newly added thought
1154
1557
  */
1155
1558
  updateMetrics(session, thought) {
1156
1559
  const metrics = session.metrics;