codemini-cli 0.3.0 → 0.3.2

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/src/core/tools.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import crypto from 'node:crypto';
4
3
  import { spawn } from 'node:child_process';
5
4
  import net from 'node:net';
6
5
  import {
@@ -16,68 +15,9 @@ import { evaluateCommandPolicy } from './command-policy.js';
16
15
  import { queryAst, readAstNode, resolveAstTarget } from './ast.js';
17
16
  import { initializeProjectIndex, queryProjectIndex, refreshIndexedFile } from './project-index.js';
18
17
  import { checkReadDedup } from './agent-loop.js';
19
-
20
- const SKIP_DIRS = new Set(['.git', 'node_modules', '.codemini', '.codemini-global', 'dist', 'coverage']);
21
- const TEXT_EXTENSIONS = new Set([
22
- '.js',
23
- '.jsx',
24
- '.ts',
25
- '.tsx',
26
- '.json',
27
- '.md',
28
- '.mjs',
29
- '.cjs',
30
- '.py',
31
- '.rb',
32
- '.go',
33
- '.rs',
34
- '.java',
35
- '.cs',
36
- '.css',
37
- '.scss',
38
- '.html',
39
- '.yml',
40
- '.yaml',
41
- '.sh',
42
- '.ps1'
43
- ]);
44
- const CODE_WRITE_GUARD_EXTENSIONS = new Set([
45
- '.js',
46
- '.jsx',
47
- '.ts',
48
- '.tsx',
49
- '.mjs',
50
- '.cjs',
51
- '.py',
52
- '.rb',
53
- '.go',
54
- '.rs',
55
- '.java',
56
- '.cs',
57
- '.css',
58
- '.scss',
59
- '.html',
60
- '.sh',
61
- '.ps1'
62
- ]);
63
- const LANGUAGE_FILE_TYPES = {
64
- js: ['js', 'jsx', 'mjs', 'cjs'],
65
- ts: ['ts', 'tsx'],
66
- py: ['py'],
67
- python: ['py'],
68
- md: ['md'],
69
- json: ['json'],
70
- css: ['css', 'scss'],
71
- html: ['html'],
72
- java: ['java'],
73
- csharp: ['cs'],
74
- cs: ['cs'],
75
- go: ['go'],
76
- rust: ['rs'],
77
- ruby: ['rb'],
78
- shell: ['sh', 'ps1'],
79
- yaml: ['yml', 'yaml']
80
- };
18
+ import { TOOL_SKIP_DIRS as SKIP_DIRS, TEXT_EXTENSIONS, CODE_WRITE_GUARD_EXTENSIONS, LANGUAGE_FILE_TYPES } from './constants.js';
19
+ import { sha256Prefixed as sha256, sha1 } from './crypto-utils.js';
20
+ import { forgetMemory, listMemories, rememberMemory, searchMemories } from './memory-store.js';
81
21
  const SERVICE_RECENT_LOG_LIMIT = 80;
82
22
  const SERVICE_STARTUP_POLL_MS = 150;
83
23
  const serviceRegistry = new Map();
@@ -97,14 +37,6 @@ function toWorkspaceRelative(root, absPath) {
97
37
  return path.relative(path.resolve(root), absPath).replace(/\\/g, '/');
98
38
  }
99
39
 
100
- function sha256(input) {
101
- return `sha256:${crypto.createHash('sha256').update(String(input || '')).digest('hex')}`;
102
- }
103
-
104
- function sha1(input) {
105
- return crypto.createHash('sha1').update(String(input || '')).digest('hex');
106
- }
107
-
108
40
  function trimLinePreview(line, maxLen = 180) {
109
41
  const text = String(line || '').replace(/\t/g, ' ').trim();
110
42
  if (text.length <= maxLen) return text;
@@ -2029,6 +1961,101 @@ export function getBuiltinTools({ workspaceRoot = process.cwd(), config, onSyste
2029
1961
  required: ['query']
2030
1962
  }
2031
1963
  }
1964
+ },
1965
+ {
1966
+ type: 'function',
1967
+ function: {
1968
+ name: 'remember_user',
1969
+ description: 'Store a durable user preference, communication habit, or long-term instruction for future sessions. Use this for things like reply style, language, explanation depth, or stable guardrails. Never store secrets, tokens, passwords, or one-off task details.',
1970
+ parameters: {
1971
+ type: 'object',
1972
+ properties: {
1973
+ content: { type: 'string', description: 'Stable preference or instruction to remember' },
1974
+ kind: { type: 'string', description: 'preference, workflow, constraint, or warning' },
1975
+ summary: { type: 'string', description: 'Short summary for the memory index' },
1976
+ replace_similar: { type: 'boolean', description: 'Replace an existing similar memory when true' }
1977
+ },
1978
+ required: ['content']
1979
+ }
1980
+ }
1981
+ },
1982
+ {
1983
+ type: 'function',
1984
+ function: {
1985
+ name: 'remember_global',
1986
+ description: 'Store a durable cross-project workflow, environment fact, or generally reusable lesson that can help across many repositories. Use this for stable habits like preferred search tools or repeatable debugging workflow. Never store secrets.',
1987
+ parameters: {
1988
+ type: 'object',
1989
+ properties: {
1990
+ content: { type: 'string' },
1991
+ kind: { type: 'string' },
1992
+ summary: { type: 'string' },
1993
+ replace_similar: { type: 'boolean' }
1994
+ },
1995
+ required: ['content']
1996
+ }
1997
+ }
1998
+ },
1999
+ {
2000
+ type: 'function',
2001
+ function: {
2002
+ name: 'remember_project',
2003
+ description: 'Store a durable project-specific convention, architecture note, key module warning, or local workflow expectation. Use this for repository-specific rules, important files, testing conventions, or architectural boundaries. Never store secrets or transient task state.',
2004
+ parameters: {
2005
+ type: 'object',
2006
+ properties: {
2007
+ content: { type: 'string' },
2008
+ kind: { type: 'string' },
2009
+ summary: { type: 'string' },
2010
+ replace_similar: { type: 'boolean' }
2011
+ },
2012
+ required: ['content']
2013
+ }
2014
+ }
2015
+ },
2016
+ {
2017
+ type: 'function',
2018
+ function: {
2019
+ name: 'list_memory',
2020
+ description: 'List stored persistent memories for one scope.',
2021
+ parameters: {
2022
+ type: 'object',
2023
+ properties: {
2024
+ scope: { type: 'string', description: 'user, global, or project' }
2025
+ },
2026
+ required: ['scope']
2027
+ }
2028
+ }
2029
+ },
2030
+ {
2031
+ type: 'function',
2032
+ function: {
2033
+ name: 'search_memory',
2034
+ description: 'Search stored persistent memories for one scope.',
2035
+ parameters: {
2036
+ type: 'object',
2037
+ properties: {
2038
+ scope: { type: 'string', description: 'user, global, or project' },
2039
+ query: { type: 'string', description: 'Search phrase' }
2040
+ },
2041
+ required: ['scope', 'query']
2042
+ }
2043
+ }
2044
+ },
2045
+ {
2046
+ type: 'function',
2047
+ function: {
2048
+ name: 'forget_memory',
2049
+ description: 'Delete a stored persistent memory by id.',
2050
+ parameters: {
2051
+ type: 'object',
2052
+ properties: {
2053
+ scope: { type: 'string', description: 'user, global, or project' },
2054
+ id: { type: 'string', description: 'Memory id to delete' }
2055
+ },
2056
+ required: ['scope', 'id']
2057
+ }
2058
+ }
2032
2059
  }
2033
2060
  ];
2034
2061
 
@@ -2249,6 +2276,55 @@ export function getBuiltinTools({ workspaceRoot = process.cwd(), config, onSyste
2249
2276
  return result;
2250
2277
  },
2251
2278
  run: (args) => runCommand(workspaceRoot, config, args),
2279
+ remember_user: async (args = {}) => {
2280
+ const saved = await rememberMemory({
2281
+ scope: 'user',
2282
+ content: args.content,
2283
+ kind: args.kind,
2284
+ summary: args.summary,
2285
+ replaceSimilar: args.replace_similar !== false,
2286
+ workspaceRoot,
2287
+ config
2288
+ });
2289
+ return { ok: true, scope: 'user', memory: saved };
2290
+ },
2291
+ remember_global: async (args = {}) => {
2292
+ const saved = await rememberMemory({
2293
+ scope: 'global',
2294
+ content: args.content,
2295
+ kind: args.kind,
2296
+ summary: args.summary,
2297
+ replaceSimilar: args.replace_similar !== false,
2298
+ workspaceRoot,
2299
+ config
2300
+ });
2301
+ return { ok: true, scope: 'global', memory: saved };
2302
+ },
2303
+ remember_project: async (args = {}) => {
2304
+ const saved = await rememberMemory({
2305
+ scope: 'project',
2306
+ content: args.content,
2307
+ kind: args.kind,
2308
+ summary: args.summary,
2309
+ replaceSimilar: args.replace_similar !== false,
2310
+ workspaceRoot,
2311
+ config
2312
+ });
2313
+ return { ok: true, scope: 'project', memory: saved };
2314
+ },
2315
+ list_memory: async (args = {}) => ({
2316
+ scope: String(args.scope || ''),
2317
+ items: await listMemories({ scope: args.scope, workspaceRoot })
2318
+ }),
2319
+ search_memory: async (args = {}) => ({
2320
+ scope: String(args.scope || ''),
2321
+ query: String(args.query || ''),
2322
+ items: await searchMemories({ scope: args.scope, query: args.query, workspaceRoot })
2323
+ }),
2324
+ forget_memory: async (args = {}) => ({
2325
+ ok: true,
2326
+ ...(await forgetMemory({ scope: args.scope, id: args.id, workspaceRoot }))
2327
+ }),
2252
2328
  start_service: (args) => startService(workspaceRoot, config, args),
2253
2329
  list_services: () => listServices(workspaceRoot),
2254
2330
  get_service_status: (args) => getServiceStatus(workspaceRoot, args),
@@ -2401,6 +2477,34 @@ export function getBuiltinTools({ workspaceRoot = process.cwd(), config, onSyste
2401
2477
  return parts.join('\n');
2402
2478
  },
2403
2479
 
2480
+ remember_user(result) {
2481
+ return result?.memory?.content ? `stored user memory: ${result.memory.content}` : JSON.stringify(result);
2482
+ },
2483
+
2484
+ remember_global(result) {
2485
+ return result?.memory?.content ? `stored global memory: ${result.memory.content}` : JSON.stringify(result);
2486
+ },
2487
+
2488
+ remember_project(result) {
2489
+ return result?.memory?.content ? `stored project memory: ${result.memory.content}` : JSON.stringify(result);
2490
+ },
2491
+
2492
+ list_memory(result) {
2493
+ if (!result || typeof result !== 'object' || !Array.isArray(result.items)) return JSON.stringify(result);
2494
+ if (result.items.length === 0) return `No ${result.scope || ''} memories found.`;
2495
+ return result.items.map((item) => `${item.id} [${item.kind}] ${item.content}`).join('\n');
2496
+ },
2497
+
2498
+ search_memory(result) {
2499
+ if (!result || typeof result !== 'object' || !Array.isArray(result.items)) return JSON.stringify(result);
2500
+ if (result.items.length === 0) return `No ${result.scope || ''} memories matched "${result.query || ''}".`;
2501
+ return result.items.map((item) => `${item.id} [${item.kind}] ${item.content}`).join('\n');
2502
+ },
2503
+
2504
+ forget_memory(result) {
2505
+ return `removed ${Number(result?.removed || 0)} memory item(s)`;
2506
+ },
2507
+
2404
2508
  generate_diff(result) {
2405
2509
  if (!result || typeof result !== 'object') return String(result);
2406
2510
  const p = result.path || '';