continuum-ai-mcp 1.0.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.
Files changed (115) hide show
  1. package/README.md +274 -0
  2. package/dist/cli/index.d.ts +3 -0
  3. package/dist/cli/index.d.ts.map +1 -0
  4. package/dist/cli/index.js +125 -0
  5. package/dist/cli/index.js.map +1 -0
  6. package/dist/database/Database.d.ts +4 -0
  7. package/dist/database/Database.d.ts.map +1 -0
  8. package/dist/database/Database.js +83 -0
  9. package/dist/database/Database.js.map +1 -0
  10. package/dist/database/schema.sql +121 -0
  11. package/dist/knowledge/KnowledgeEngine.d.ts +63 -0
  12. package/dist/knowledge/KnowledgeEngine.d.ts.map +1 -0
  13. package/dist/knowledge/KnowledgeEngine.js +190 -0
  14. package/dist/knowledge/KnowledgeEngine.js.map +1 -0
  15. package/dist/languages/LanguageRegistry.d.ts +38 -0
  16. package/dist/languages/LanguageRegistry.d.ts.map +1 -0
  17. package/dist/languages/LanguageRegistry.js +233 -0
  18. package/dist/languages/LanguageRegistry.js.map +1 -0
  19. package/dist/languages/definitions/cpp.d.ts +2 -0
  20. package/dist/languages/definitions/cpp.d.ts.map +1 -0
  21. package/dist/languages/definitions/cpp.js +25 -0
  22. package/dist/languages/definitions/cpp.js.map +1 -0
  23. package/dist/languages/definitions/csharp.d.ts +2 -0
  24. package/dist/languages/definitions/csharp.d.ts.map +1 -0
  25. package/dist/languages/definitions/csharp.js +40 -0
  26. package/dist/languages/definitions/csharp.js.map +1 -0
  27. package/dist/languages/definitions/go.d.ts +2 -0
  28. package/dist/languages/definitions/go.d.ts.map +1 -0
  29. package/dist/languages/definitions/go.js +21 -0
  30. package/dist/languages/definitions/go.js.map +1 -0
  31. package/dist/languages/definitions/java.d.ts +2 -0
  32. package/dist/languages/definitions/java.d.ts.map +1 -0
  33. package/dist/languages/definitions/java.js +32 -0
  34. package/dist/languages/definitions/java.js.map +1 -0
  35. package/dist/languages/definitions/javascript.d.ts +2 -0
  36. package/dist/languages/definitions/javascript.d.ts.map +1 -0
  37. package/dist/languages/definitions/javascript.js +26 -0
  38. package/dist/languages/definitions/javascript.js.map +1 -0
  39. package/dist/languages/definitions/kotlin.d.ts +2 -0
  40. package/dist/languages/definitions/kotlin.d.ts.map +1 -0
  41. package/dist/languages/definitions/kotlin.js +36 -0
  42. package/dist/languages/definitions/kotlin.js.map +1 -0
  43. package/dist/languages/definitions/markdown.d.ts +2 -0
  44. package/dist/languages/definitions/markdown.d.ts.map +1 -0
  45. package/dist/languages/definitions/markdown.js +18 -0
  46. package/dist/languages/definitions/markdown.js.map +1 -0
  47. package/dist/languages/definitions/php.d.ts +2 -0
  48. package/dist/languages/definitions/php.d.ts.map +1 -0
  49. package/dist/languages/definitions/php.js +27 -0
  50. package/dist/languages/definitions/php.js.map +1 -0
  51. package/dist/languages/definitions/python.d.ts +2 -0
  52. package/dist/languages/definitions/python.d.ts.map +1 -0
  53. package/dist/languages/definitions/python.js +17 -0
  54. package/dist/languages/definitions/python.js.map +1 -0
  55. package/dist/languages/definitions/ruby.d.ts +2 -0
  56. package/dist/languages/definitions/ruby.d.ts.map +1 -0
  57. package/dist/languages/definitions/ruby.js +16 -0
  58. package/dist/languages/definitions/ruby.js.map +1 -0
  59. package/dist/languages/definitions/rust.d.ts +2 -0
  60. package/dist/languages/definitions/rust.d.ts.map +1 -0
  61. package/dist/languages/definitions/rust.js +28 -0
  62. package/dist/languages/definitions/rust.js.map +1 -0
  63. package/dist/languages/definitions/sql.d.ts +2 -0
  64. package/dist/languages/definitions/sql.d.ts.map +1 -0
  65. package/dist/languages/definitions/sql.js +36 -0
  66. package/dist/languages/definitions/sql.js.map +1 -0
  67. package/dist/languages/definitions/swift.d.ts +2 -0
  68. package/dist/languages/definitions/swift.d.ts.map +1 -0
  69. package/dist/languages/definitions/swift.js +40 -0
  70. package/dist/languages/definitions/swift.js.map +1 -0
  71. package/dist/languages/definitions/typescript.d.ts +2 -0
  72. package/dist/languages/definitions/typescript.d.ts.map +1 -0
  73. package/dist/languages/definitions/typescript.js +40 -0
  74. package/dist/languages/definitions/typescript.js.map +1 -0
  75. package/dist/mcp/McpServer.d.ts +2 -0
  76. package/dist/mcp/McpServer.d.ts.map +1 -0
  77. package/dist/mcp/McpServer.js +262 -0
  78. package/dist/mcp/McpServer.js.map +1 -0
  79. package/dist/parser/IncrementalParser.d.ts +25 -0
  80. package/dist/parser/IncrementalParser.d.ts.map +1 -0
  81. package/dist/parser/IncrementalParser.js +195 -0
  82. package/dist/parser/IncrementalParser.js.map +1 -0
  83. package/dist/schema/ISchemaAdapter.d.ts +20 -0
  84. package/dist/schema/ISchemaAdapter.d.ts.map +1 -0
  85. package/dist/schema/ISchemaAdapter.js +3 -0
  86. package/dist/schema/ISchemaAdapter.js.map +1 -0
  87. package/dist/schema/MssqlAdapter.d.ts +6 -0
  88. package/dist/schema/MssqlAdapter.d.ts.map +1 -0
  89. package/dist/schema/MssqlAdapter.js +139 -0
  90. package/dist/schema/MssqlAdapter.js.map +1 -0
  91. package/dist/schema/MySqlAdapter.d.ts +6 -0
  92. package/dist/schema/MySqlAdapter.d.ts.map +1 -0
  93. package/dist/schema/MySqlAdapter.js +77 -0
  94. package/dist/schema/MySqlAdapter.js.map +1 -0
  95. package/dist/schema/PostgresAdapter.d.ts +6 -0
  96. package/dist/schema/PostgresAdapter.d.ts.map +1 -0
  97. package/dist/schema/PostgresAdapter.js +78 -0
  98. package/dist/schema/PostgresAdapter.js.map +1 -0
  99. package/dist/schema/SchemaReader.d.ts +17 -0
  100. package/dist/schema/SchemaReader.d.ts.map +1 -0
  101. package/dist/schema/SchemaReader.js +82 -0
  102. package/dist/schema/SchemaReader.js.map +1 -0
  103. package/dist/session/SessionEngine.d.ts +40 -0
  104. package/dist/session/SessionEngine.d.ts.map +1 -0
  105. package/dist/session/SessionEngine.js +131 -0
  106. package/dist/session/SessionEngine.js.map +1 -0
  107. package/dist/utils/logger.d.ts +3 -0
  108. package/dist/utils/logger.d.ts.map +1 -0
  109. package/dist/utils/logger.js +54 -0
  110. package/dist/utils/logger.js.map +1 -0
  111. package/dist/watcher/FileWatcher.d.ts +19 -0
  112. package/dist/watcher/FileWatcher.d.ts.map +1 -0
  113. package/dist/watcher/FileWatcher.js +146 -0
  114. package/dist/watcher/FileWatcher.js.map +1 -0
  115. package/package.json +54 -0
@@ -0,0 +1,139 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MssqlAdapter = void 0;
37
+ const sql = __importStar(require("mssql"));
38
+ const logger_1 = require("../utils/logger");
39
+ const config = {
40
+ server: process.env.MSSQL_HOST || 'localhost',
41
+ port: parseInt(process.env.MSSQL_PORT || '1433'),
42
+ database: process.env.MSSQL_DATABASE || '',
43
+ user: process.env.MSSQL_USER || '',
44
+ password: process.env.MSSQL_PASSWORD || '',
45
+ options: {
46
+ trustServerCertificate: true,
47
+ encrypt: false,
48
+ },
49
+ connectionTimeout: 8000,
50
+ requestTimeout: 8000,
51
+ pool: {
52
+ max: 5,
53
+ min: 0,
54
+ idleTimeoutMillis: 30000,
55
+ },
56
+ };
57
+ let pool = null;
58
+ async function getPool() {
59
+ if (!pool || !pool.connected) {
60
+ pool = await new sql.ConnectionPool(config).connect();
61
+ logger_1.logger.info('MSSQL connection pool established');
62
+ }
63
+ return pool;
64
+ }
65
+ class MssqlAdapter {
66
+ async getSchema(tableName) {
67
+ try {
68
+ const p = await getPool();
69
+ const columnsResult = await p
70
+ .request()
71
+ .input('table', sql.VarChar, tableName)
72
+ .query(`
73
+ SELECT
74
+ c.COLUMN_NAME AS column_name,
75
+ c.DATA_TYPE AS data_type,
76
+ c.IS_NULLABLE AS is_nullable,
77
+ c.CHARACTER_MAXIMUM_LENGTH AS max_length,
78
+ CASE WHEN pk.COLUMN_NAME IS NOT NULL THEN 1 ELSE 0 END AS is_primary_key,
79
+ fk_col.TABLE_NAME AS foreign_key_table,
80
+ fk_col.COLUMN_NAME AS foreign_key_column
81
+ FROM INFORMATION_SCHEMA.COLUMNS c
82
+ LEFT JOIN (
83
+ SELECT ku.COLUMN_NAME
84
+ FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
85
+ JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku
86
+ ON tc.CONSTRAINT_NAME = ku.CONSTRAINT_NAME
87
+ WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY' AND tc.TABLE_NAME = @table
88
+ ) pk ON c.COLUMN_NAME = pk.COLUMN_NAME
89
+ LEFT JOIN (
90
+ SELECT kcu.COLUMN_NAME, ccu.TABLE_NAME, ccu.COLUMN_NAME AS FK_COLUMN
91
+ FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
92
+ JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu ON rc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
93
+ JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu
94
+ ON rc.UNIQUE_CONSTRAINT_NAME = ccu.CONSTRAINT_NAME
95
+ WHERE kcu.TABLE_NAME = @table
96
+ ) fk_col ON c.COLUMN_NAME = fk_col.COLUMN_NAME
97
+ WHERE c.TABLE_NAME = @table
98
+ ORDER BY c.ORDINAL_POSITION
99
+ `);
100
+ if (columnsResult.recordset.length === 0)
101
+ return null;
102
+ const indexResult = await p
103
+ .request()
104
+ .input('table', sql.VarChar, tableName)
105
+ .query(`
106
+ SELECT i.name AS index_name
107
+ FROM sys.indexes i
108
+ JOIN sys.tables t ON i.object_id = t.object_id
109
+ WHERE t.name = @table AND i.name IS NOT NULL
110
+ `);
111
+ return {
112
+ table_name: tableName,
113
+ columns: columnsResult.recordset,
114
+ indexes: indexResult.recordset.map((r) => r.index_name),
115
+ };
116
+ }
117
+ catch (err) {
118
+ logger_1.logger.error({ err, tableName }, 'MSSQL getSchema failed');
119
+ return null;
120
+ }
121
+ }
122
+ async listTables() {
123
+ try {
124
+ const p = await getPool();
125
+ const result = await p.request().query(`
126
+ SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
127
+ WHERE TABLE_TYPE = 'BASE TABLE'
128
+ ORDER BY TABLE_NAME
129
+ `);
130
+ return result.recordset.map((r) => r.TABLE_NAME);
131
+ }
132
+ catch (err) {
133
+ logger_1.logger.error({ err }, 'MSSQL listTables failed');
134
+ return [];
135
+ }
136
+ }
137
+ }
138
+ exports.MssqlAdapter = MssqlAdapter;
139
+ //# sourceMappingURL=MssqlAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MssqlAdapter.js","sourceRoot":"","sources":["../../src/schema/MssqlAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { ISchemaAdapter, TableSchema } from './ISchemaAdapter';
2
+ export declare class MySqlAdapter implements ISchemaAdapter {
3
+ getSchema(tableName: string): Promise<TableSchema | null>;
4
+ listTables(): Promise<string[]>;
5
+ }
6
+ //# sourceMappingURL=MySqlAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MySqlAdapter.d.ts","sourceRoot":"","sources":["../../src/schema/MySqlAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAe/D,qBAAa,YAAa,YAAW,cAAc;IAC3C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAgDzD,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CActC"}
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MySqlAdapter = void 0;
7
+ const promise_1 = __importDefault(require("mysql2/promise"));
8
+ const logger_1 = require("../utils/logger");
9
+ const pool = promise_1.default.createPool({
10
+ host: process.env.MYSQL_HOST || 'localhost',
11
+ port: parseInt(process.env.MYSQL_PORT || '3306'),
12
+ database: process.env.MYSQL_DATABASE || '',
13
+ user: process.env.MYSQL_USER || '',
14
+ password: process.env.MYSQL_PASSWORD || '',
15
+ waitForConnections: true,
16
+ connectionLimit: 5,
17
+ queueLimit: 0,
18
+ connectTimeout: 8000,
19
+ });
20
+ class MySqlAdapter {
21
+ async getSchema(tableName) {
22
+ const conn = await pool.getConnection();
23
+ try {
24
+ const [cols] = await conn.query(`
25
+ SELECT
26
+ c.COLUMN_NAME AS column_name,
27
+ c.DATA_TYPE AS data_type,
28
+ c.IS_NULLABLE AS is_nullable,
29
+ c.CHARACTER_MAXIMUM_LENGTH AS max_length,
30
+ IF(c.COLUMN_KEY = 'PRI', 1, 0) AS is_primary_key,
31
+ kcu.REFERENCED_TABLE_NAME AS foreign_key_table,
32
+ kcu.REFERENCED_COLUMN_NAME AS foreign_key_column
33
+ FROM information_schema.COLUMNS c
34
+ LEFT JOIN information_schema.KEY_COLUMN_USAGE kcu
35
+ ON c.TABLE_NAME = kcu.TABLE_NAME
36
+ AND c.COLUMN_NAME = kcu.COLUMN_NAME
37
+ AND c.TABLE_SCHEMA = kcu.TABLE_SCHEMA
38
+ AND kcu.REFERENCED_TABLE_NAME IS NOT NULL
39
+ WHERE c.TABLE_NAME = ?
40
+ AND c.TABLE_SCHEMA = DATABASE()
41
+ ORDER BY c.ORDINAL_POSITION
42
+ `, [tableName]);
43
+ if (cols.length === 0)
44
+ return null;
45
+ const [idxs] = await conn.query(`SHOW INDEX FROM \`${tableName}\``, []);
46
+ const uniqueIndexNames = [...new Set(idxs.map((r) => r['Key_name']))];
47
+ return {
48
+ table_name: tableName,
49
+ columns: cols,
50
+ indexes: uniqueIndexNames,
51
+ };
52
+ }
53
+ catch (err) {
54
+ logger_1.logger.error({ err, tableName }, 'MySQL getSchema failed');
55
+ return null;
56
+ }
57
+ finally {
58
+ conn.release();
59
+ }
60
+ }
61
+ async listTables() {
62
+ const conn = await pool.getConnection();
63
+ try {
64
+ const [rows] = await conn.query(`SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'`);
65
+ return rows.map((r) => Object.values(r)[0]);
66
+ }
67
+ catch (err) {
68
+ logger_1.logger.error({ err }, 'MySQL listTables failed');
69
+ return [];
70
+ }
71
+ finally {
72
+ conn.release();
73
+ }
74
+ }
75
+ }
76
+ exports.MySqlAdapter = MySqlAdapter;
77
+ //# sourceMappingURL=MySqlAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MySqlAdapter.js","sourceRoot":"","sources":["../../src/schema/MySqlAdapter.ts"],"names":[],"mappings":";;;;;;AAAA,6DAAmC;AAEnC,4CAAyC;AAEzC,MAAM,IAAI,GAAG,iBAAK,CAAC,UAAU,CAAC;IAC5B,IAAI,EAAgB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAQ,WAAW;IAC7D,IAAI,EAAgB,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,MAAM,CAAC;IAC9D,QAAQ,EAAY,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE;IACpD,IAAI,EAAgB,OAAO,CAAC,GAAG,CAAC,UAAU,IAAQ,EAAE;IACpD,QAAQ,EAAY,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE;IACpD,kBAAkB,EAAE,IAAI;IACxB,eAAe,EAAK,CAAC;IACrB,UAAU,EAAU,CAAC;IACrB,cAAc,EAAM,IAAI;CACzB,CAAC,CAAC;AAEH,MAAa,YAAY;IACvB,KAAK,CAAC,SAAS,CAAC,SAAiB;QAC/B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;;;;;;;;;;;;;;;;SAkBC,EACD,CAAC,SAAS,CAAC,CACZ,CAAC;YAEF,IAAK,IAAkB,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAElD,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,qBAAqB,SAAS,IAAI,EAClC,EAAE,CACH,CAAC;YAEF,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAE,IAA8B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAW,CAAC,CAAC,CAAC,CAAC;YAE3G,OAAO;gBACL,UAAU,EAAE,SAAS;gBACrB,OAAO,EAAE,IAA8B;gBACvC,OAAO,EAAE,gBAAgB;aAC1B,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,wBAAwB,CAAC,CAAC;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,kDAAkD,CACnD,CAAC;YACF,OAAQ,IAA8B,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAW,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,yBAAyB,CAAC,CAAC;YACjD,OAAO,EAAE,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;CACF;AA/DD,oCA+DC"}
@@ -0,0 +1,6 @@
1
+ import { ISchemaAdapter, TableSchema } from './ISchemaAdapter';
2
+ export declare class PostgresAdapter implements ISchemaAdapter {
3
+ getSchema(tableName: string): Promise<TableSchema | null>;
4
+ listTables(): Promise<string[]>;
5
+ }
6
+ //# sourceMappingURL=PostgresAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresAdapter.d.ts","sourceRoot":"","sources":["../../src/schema/PostgresAdapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAc/D,qBAAa,eAAgB,YAAW,cAAc;IAC9C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAgDzD,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAgBtC"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgresAdapter = void 0;
4
+ const pg_1 = require("pg");
5
+ const logger_1 = require("../utils/logger");
6
+ const pool = new pg_1.Pool({
7
+ host: process.env.PG_HOST || 'localhost',
8
+ port: parseInt(process.env.PG_PORT || '5432'),
9
+ database: process.env.PG_DATABASE || '',
10
+ user: process.env.PG_USER || '',
11
+ password: process.env.PG_PASSWORD || '',
12
+ max: 5,
13
+ idleTimeoutMillis: 30000,
14
+ connectionTimeoutMillis: 8000,
15
+ });
16
+ class PostgresAdapter {
17
+ async getSchema(tableName) {
18
+ const client = await pool.connect();
19
+ try {
20
+ const colsRes = await client.query(`
21
+ SELECT
22
+ c.column_name,
23
+ c.data_type,
24
+ c.is_nullable,
25
+ c.character_maximum_length AS max_length,
26
+ (tc.constraint_type = 'PRIMARY KEY') AS is_primary_key,
27
+ ccu.table_name AS foreign_key_table,
28
+ ccu.column_name AS foreign_key_column
29
+ FROM information_schema.columns c
30
+ LEFT JOIN information_schema.key_column_usage kcu
31
+ ON c.table_name = kcu.table_name AND c.column_name = kcu.column_name
32
+ LEFT JOIN information_schema.table_constraints tc
33
+ ON kcu.constraint_name = tc.constraint_name
34
+ LEFT JOIN information_schema.referential_constraints rc
35
+ ON kcu.constraint_name = rc.constraint_name
36
+ LEFT JOIN information_schema.constraint_column_usage ccu
37
+ ON rc.unique_constraint_name = ccu.constraint_name
38
+ WHERE c.table_name = $1
39
+ ORDER BY c.ordinal_position
40
+ `, [tableName]);
41
+ if (colsRes.rows.length === 0)
42
+ return null;
43
+ const idxRes = await client.query(`SELECT indexname AS index_name FROM pg_indexes WHERE tablename = $1`, [tableName]);
44
+ return {
45
+ table_name: tableName,
46
+ columns: colsRes.rows,
47
+ indexes: idxRes.rows.map((r) => r.index_name),
48
+ };
49
+ }
50
+ catch (err) {
51
+ logger_1.logger.error({ err, tableName }, 'Postgres getSchema failed');
52
+ return null;
53
+ }
54
+ finally {
55
+ client.release();
56
+ }
57
+ }
58
+ async listTables() {
59
+ const client = await pool.connect();
60
+ try {
61
+ const res = await client.query(`
62
+ SELECT table_name FROM information_schema.tables
63
+ WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
64
+ ORDER BY table_name
65
+ `);
66
+ return res.rows.map((r) => r.table_name);
67
+ }
68
+ catch (err) {
69
+ logger_1.logger.error({ err }, 'Postgres listTables failed');
70
+ return [];
71
+ }
72
+ finally {
73
+ client.release();
74
+ }
75
+ }
76
+ }
77
+ exports.PostgresAdapter = PostgresAdapter;
78
+ //# sourceMappingURL=PostgresAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostgresAdapter.js","sourceRoot":"","sources":["../../src/schema/PostgresAdapter.ts"],"names":[],"mappings":";;;AAAA,2BAA0B;AAE1B,4CAAyC;AAEzC,MAAM,IAAI,GAAG,IAAI,SAAI,CAAC;IACpB,IAAI,EAAM,OAAO,CAAC,GAAG,CAAC,OAAO,IAAQ,WAAW;IAChD,IAAI,EAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,MAAM,CAAC;IACjD,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE;IACvC,IAAI,EAAM,OAAO,CAAC,GAAG,CAAC,OAAO,IAAQ,EAAE;IACvC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE;IACvC,GAAG,EAAO,CAAC;IACX,iBAAiB,EAAE,KAAK;IACxB,uBAAuB,EAAE,IAAI;CAC9B,CAAC,CAAC;AAEH,MAAa,eAAe;IAC1B,KAAK,CAAC,SAAS,CAAC,SAAiB;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,KAAK,CAChC;;;;;;;;;;;;;;;;;;;;SAoBC,EACD,CAAC,SAAS,CAAC,CACZ,CAAC;YAEF,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YAE3C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAC/B,qEAAqE,EACrE,CAAC,SAAS,CAAC,CACZ,CAAC;YAEF,OAAO;gBACL,UAAU,EAAE,SAAS;gBACrB,OAAO,EAAE,OAAO,CAAC,IAAI;gBACrB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;aACtE,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,2BAA2B,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC;;;;OAI9B,CAAC,CAAC;YACH,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,4BAA4B,CAAC,CAAC;YACpD,OAAO,EAAE,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;CACF;AAjED,0CAiEC"}
@@ -0,0 +1,17 @@
1
+ import { TableSchema } from './ISchemaAdapter';
2
+ /**
3
+ * DB-agnostic Schema Reader (Strategy pattern).
4
+ *
5
+ * Wraps any ISchemaAdapter (MSSQL | Postgres | MySQL) with a SQLite cache
6
+ * so repeated tool calls don't hammer the database.
7
+ *
8
+ * Select adapter via DB_TYPE env var: 'mssql' | 'postgres' | 'mysql'
9
+ */
10
+ export declare class SchemaReader {
11
+ private adapter;
12
+ constructor();
13
+ isEnabled(): boolean;
14
+ getSchema(tableName: string): Promise<TableSchema | null>;
15
+ listTables(): Promise<string[]>;
16
+ }
17
+ //# sourceMappingURL=SchemaReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaReader.d.ts","sourceRoot":"","sources":["../../src/schema/SchemaReader.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAK/D;;;;;;;GAOG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAA+B;;IA4B9C,SAAS,IAAI,OAAO;IAId,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAoCzD,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAItC"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SchemaReader = void 0;
4
+ const Database_1 = require("../database/Database");
5
+ const logger_1 = require("../utils/logger");
6
+ const CACHE_TTL_SECONDS = 3600; // 1 hour
7
+ /**
8
+ * DB-agnostic Schema Reader (Strategy pattern).
9
+ *
10
+ * Wraps any ISchemaAdapter (MSSQL | Postgres | MySQL) with a SQLite cache
11
+ * so repeated tool calls don't hammer the database.
12
+ *
13
+ * Select adapter via DB_TYPE env var: 'mssql' | 'postgres' | 'mysql'
14
+ */
15
+ class SchemaReader {
16
+ adapter = null;
17
+ constructor() {
18
+ const dbType = process.env.DB_TYPE?.toLowerCase();
19
+ if (!dbType) {
20
+ logger_1.logger.info('No DB_TYPE set - get_schema tool will be disabled');
21
+ return;
22
+ }
23
+ // Lazy-require adapters so unused DB drivers don't crash on import
24
+ try {
25
+ if (dbType === 'mssql') {
26
+ const { MssqlAdapter } = require('./MssqlAdapter');
27
+ this.adapter = new MssqlAdapter();
28
+ }
29
+ else if (dbType === 'postgres' || dbType === 'postgresql') {
30
+ const { PostgresAdapter } = require('./PostgresAdapter');
31
+ this.adapter = new PostgresAdapter();
32
+ }
33
+ else if (dbType === 'mysql') {
34
+ const { MySqlAdapter } = require('./MySqlAdapter');
35
+ this.adapter = new MySqlAdapter();
36
+ }
37
+ else {
38
+ logger_1.logger.warn({ dbType }, 'Unknown DB_TYPE - supported: mssql | postgres | mysql');
39
+ }
40
+ }
41
+ catch (err) {
42
+ logger_1.logger.error({ err, dbType }, 'Failed to initialise schema adapter');
43
+ }
44
+ }
45
+ isEnabled() {
46
+ return this.adapter !== null;
47
+ }
48
+ async getSchema(tableName) {
49
+ if (!this.adapter)
50
+ return null;
51
+ const db = (0, Database_1.getDb)();
52
+ // Serve from cache if fresh
53
+ const cached = db
54
+ .prepare(`SELECT schema_json, cached_at FROM schema_cache
55
+ WHERE table_name = ? AND cached_at > unixepoch() - ?`)
56
+ .get(tableName, CACHE_TTL_SECONDS);
57
+ if (cached) {
58
+ logger_1.logger.debug({ tableName }, 'Schema cache hit');
59
+ return JSON.parse(cached.schema_json);
60
+ }
61
+ const tableSchema = await this.adapter.getSchema(tableName);
62
+ if (!tableSchema)
63
+ return null;
64
+ // Cache it
65
+ db.prepare(`
66
+ INSERT INTO schema_cache (table_name, schema_json, cached_at)
67
+ VALUES (?, ?, unixepoch())
68
+ ON CONFLICT(table_name) DO UPDATE SET
69
+ schema_json = excluded.schema_json,
70
+ cached_at = excluded.cached_at
71
+ `).run(tableName, JSON.stringify(tableSchema));
72
+ logger_1.logger.info({ tableName }, 'Schema fetched and cached');
73
+ return tableSchema;
74
+ }
75
+ async listTables() {
76
+ if (!this.adapter)
77
+ return [];
78
+ return this.adapter.listTables();
79
+ }
80
+ }
81
+ exports.SchemaReader = SchemaReader;
82
+ //# sourceMappingURL=SchemaReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaReader.js","sourceRoot":"","sources":["../../src/schema/SchemaReader.ts"],"names":[],"mappings":";;;AAAA,mDAA6C;AAE7C,4CAAyC;AAEzC,MAAM,iBAAiB,GAAG,IAAI,CAAC,CAAC,SAAS;AAEzC;;;;;;;GAOG;AACH,MAAa,YAAY;IACf,OAAO,GAA0B,IAAI,CAAC;IAE9C;QACE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;QAClD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,eAAM,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;YACjE,OAAO;QACT,CAAC;QAED,mEAAmE;QACnE,IAAI,CAAC;YACH,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAoC,CAAC;gBACtF,IAAI,CAAC,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;YACpC,CAAC;iBAAM,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;gBAC5D,MAAM,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAuC,CAAC;gBAC/F,IAAI,CAAC,OAAO,GAAG,IAAI,eAAe,EAAE,CAAC;YACvC,CAAC;iBAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBAC9B,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAoC,CAAC;gBACtF,IAAI,CAAC,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;YACpC,CAAC;iBAAM,CAAC;gBACN,eAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,uDAAuD,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,eAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,qCAAqC,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,SAAiB;QAC/B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE/B,MAAM,EAAE,GAAG,IAAA,gBAAK,GAAE,CAAC;QAEnB,4BAA4B;QAC5B,MAAM,MAAM,GAAG,EAAE;aACd,OAAO,CACN;8DACsD,CACvD;aACA,GAAG,CAAC,SAAS,EAAE,iBAAiB,CAEtB,CAAC;QAEd,IAAI,MAAM,EAAE,CAAC;YACX,eAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,EAAE,kBAAkB,CAAC,CAAC;YAChD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAgB,CAAC;QACvD,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAE9B,WAAW;QACX,EAAE,CAAC,OAAO,CAAC;;;;;;KAMV,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC;QAE/C,eAAM,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,2BAA2B,CAAC,CAAC;QACxD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IACnC,CAAC;CACF;AAzED,oCAyEC"}
@@ -0,0 +1,40 @@
1
+ export interface TaskState {
2
+ goal: string;
3
+ decisions: string[];
4
+ next_steps: string[];
5
+ open_questions: string[];
6
+ }
7
+ export interface TouchedFile {
8
+ path: string;
9
+ action: string;
10
+ touched_at: number;
11
+ }
12
+ export interface SessionState {
13
+ session_id: string;
14
+ goal: string | null;
15
+ started_at: number;
16
+ compaction_count: number;
17
+ touched_files: TouchedFile[];
18
+ latest_task: TaskState | null;
19
+ }
20
+ export declare class SessionEngine {
21
+ private readonly sessionId;
22
+ private readonly startTime;
23
+ constructor();
24
+ private initSession;
25
+ getSessionId(): string;
26
+ getUptimeSeconds(): number;
27
+ /**
28
+ * Record a file being touched. Action 'opened' is separate from watcher events.
29
+ * Skips duplicate entries within 5 seconds (debounce for rapid saves).
30
+ */
31
+ recordFileTouch(filePath: string, action: 'opened' | 'modified' | 'created' | 'deleted'): void;
32
+ /** Save structured task state. Returns the task ID. */
33
+ saveTask(task: TaskState): number;
34
+ /** Full session state — the primary recovery payload after compaction. */
35
+ getSession(): SessionState;
36
+ /** Distinct files touched this session — useful for impact analysis. */
37
+ getTouchedFiles(): TouchedFile[];
38
+ recordCompaction(): void;
39
+ }
40
+ //# sourceMappingURL=SessionEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionEngine.d.ts","sourceRoot":"","sources":["../../src/session/SessionEngine.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,WAAW,EAAE,SAAS,GAAG,IAAI,CAAC;CAC/B;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;;IAOnC,OAAO,CAAC,WAAW;IAWnB,YAAY,IAAI,MAAM;IAItB,gBAAgB,IAAI,MAAM;IAI1B;;;OAGG;IACH,eAAe,CACb,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GACpD,IAAI;IAwBP,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM;IAwBjC,0EAA0E;IAC1E,UAAU,IAAI,YAAY;IAwD1B,wEAAwE;IACxE,eAAe,IAAI,WAAW,EAAE;IAahC,gBAAgB,IAAI,IAAI;CASzB"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionEngine = void 0;
4
+ const Database_1 = require("../database/Database");
5
+ const crypto_1 = require("crypto");
6
+ const logger_1 = require("../utils/logger");
7
+ class SessionEngine {
8
+ sessionId;
9
+ startTime;
10
+ constructor() {
11
+ this.startTime = Math.floor(Date.now() / 1000);
12
+ this.sessionId = this.initSession();
13
+ }
14
+ initSession() {
15
+ const db = (0, Database_1.getDb)();
16
+ const id = (0, crypto_1.randomUUID)();
17
+ db.prepare(`
18
+ INSERT INTO sessions (id, started_at, updated_at)
19
+ VALUES (?, unixepoch(), unixepoch())
20
+ `).run(id);
21
+ logger_1.logger.info({ sessionId: id }, 'Session started');
22
+ return id;
23
+ }
24
+ getSessionId() {
25
+ return this.sessionId;
26
+ }
27
+ getUptimeSeconds() {
28
+ return Math.floor(Date.now() / 1000) - this.startTime;
29
+ }
30
+ /**
31
+ * Record a file being touched. Action 'opened' is separate from watcher events.
32
+ * Skips duplicate entries within 5 seconds (debounce for rapid saves).
33
+ */
34
+ recordFileTouch(filePath, action) {
35
+ const db = (0, Database_1.getDb)();
36
+ // Debounce: skip if same file+action recorded in last 5 seconds
37
+ const recent = db
38
+ .prepare(`
39
+ SELECT id FROM touched_files
40
+ WHERE session_id = ? AND path = ? AND action = ?
41
+ AND touched_at > unixepoch() - 5
42
+ `)
43
+ .get(this.sessionId, filePath, action);
44
+ if (recent)
45
+ return;
46
+ db.prepare(`
47
+ INSERT INTO touched_files (session_id, path, action, touched_at)
48
+ VALUES (?, ?, ?, unixepoch())
49
+ `).run(this.sessionId, filePath, action);
50
+ db.prepare(`
51
+ UPDATE sessions SET updated_at = unixepoch() WHERE id = ?
52
+ `).run(this.sessionId);
53
+ }
54
+ /** Save structured task state. Returns the task ID. */
55
+ saveTask(task) {
56
+ const db = (0, Database_1.getDb)();
57
+ const result = db
58
+ .prepare(`
59
+ INSERT INTO tasks (session_id, goal, decisions, next_steps, open_questions, saved_at)
60
+ VALUES (?, ?, ?, ?, ?, unixepoch())
61
+ `)
62
+ .run(this.sessionId, task.goal, JSON.stringify(task.decisions), JSON.stringify(task.next_steps), JSON.stringify(task.open_questions));
63
+ db.prepare(`UPDATE sessions SET goal = ?, updated_at = unixepoch() WHERE id = ?`).run(task.goal, this.sessionId);
64
+ logger_1.logger.info({ sessionId: this.sessionId, taskId: result.lastInsertRowid }, 'Task saved');
65
+ return Number(result.lastInsertRowid);
66
+ }
67
+ /** Full session state — the primary recovery payload after compaction. */
68
+ getSession() {
69
+ const db = (0, Database_1.getDb)();
70
+ const session = db
71
+ .prepare('SELECT * FROM sessions WHERE id = ?')
72
+ .get(this.sessionId);
73
+ const touched = db
74
+ .prepare(`
75
+ SELECT path, action, MAX(touched_at) as touched_at
76
+ FROM touched_files
77
+ WHERE session_id = ?
78
+ GROUP BY path
79
+ ORDER BY touched_at DESC
80
+ LIMIT 100
81
+ `)
82
+ .all(this.sessionId);
83
+ const latestTask = db
84
+ .prepare(`
85
+ SELECT * FROM tasks
86
+ WHERE session_id = ?
87
+ ORDER BY saved_at DESC
88
+ LIMIT 1
89
+ `)
90
+ .get(this.sessionId);
91
+ return {
92
+ session_id: session.id,
93
+ goal: session.goal,
94
+ started_at: session.started_at,
95
+ compaction_count: session.compaction_count,
96
+ touched_files: touched,
97
+ latest_task: latestTask
98
+ ? {
99
+ goal: latestTask.goal,
100
+ decisions: JSON.parse(latestTask.decisions || '[]'),
101
+ next_steps: JSON.parse(latestTask.next_steps || '[]'),
102
+ open_questions: JSON.parse(latestTask.open_questions || '[]'),
103
+ }
104
+ : null,
105
+ };
106
+ }
107
+ /** Distinct files touched this session — useful for impact analysis. */
108
+ getTouchedFiles() {
109
+ const db = (0, Database_1.getDb)();
110
+ return db
111
+ .prepare(`
112
+ SELECT path, action, MAX(touched_at) as touched_at
113
+ FROM touched_files
114
+ WHERE session_id = ?
115
+ GROUP BY path
116
+ ORDER BY touched_at DESC
117
+ `)
118
+ .all(this.sessionId);
119
+ }
120
+ recordCompaction() {
121
+ const db = (0, Database_1.getDb)();
122
+ db.prepare(`
123
+ UPDATE sessions
124
+ SET compaction_count = compaction_count + 1, updated_at = unixepoch()
125
+ WHERE id = ?
126
+ `).run(this.sessionId);
127
+ logger_1.logger.info({ sessionId: this.sessionId }, 'Context compaction recorded');
128
+ }
129
+ }
130
+ exports.SessionEngine = SessionEngine;
131
+ //# sourceMappingURL=SessionEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SessionEngine.js","sourceRoot":"","sources":["../../src/session/SessionEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import pino from 'pino';
2
+ export declare const logger: pino.Logger<never, boolean>;
3
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAaxB,eAAO,MAAM,MAAM,6BAOlB,CAAC"}