@hotmeshio/hotmesh 0.5.1 → 0.5.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.
Files changed (39) hide show
  1. package/README.md +9 -5
  2. package/build/package.json +16 -14
  3. package/build/services/hotmesh/index.d.ts +9 -11
  4. package/build/services/hotmesh/index.js +9 -11
  5. package/build/services/memflow/entity.d.ts +168 -4
  6. package/build/services/memflow/entity.js +177 -15
  7. package/build/services/memflow/workflow/index.d.ts +2 -4
  8. package/build/services/memflow/workflow/index.js +2 -4
  9. package/build/services/memflow/workflow/interruption.d.ts +6 -4
  10. package/build/services/memflow/workflow/interruption.js +6 -4
  11. package/build/services/memflow/workflow/waitFor.js +1 -0
  12. package/build/services/search/index.d.ts +10 -0
  13. package/build/services/search/providers/postgres/postgres.d.ts +12 -0
  14. package/build/services/search/providers/postgres/postgres.js +209 -0
  15. package/build/services/search/providers/redis/ioredis.d.ts +4 -0
  16. package/build/services/search/providers/redis/ioredis.js +13 -0
  17. package/build/services/search/providers/redis/redis.d.ts +4 -0
  18. package/build/services/search/providers/redis/redis.js +13 -0
  19. package/build/services/store/providers/postgres/kvsql.d.ts +13 -37
  20. package/build/services/store/providers/postgres/kvsql.js +2 -2
  21. package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +16 -0
  22. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +480 -0
  23. package/build/services/store/providers/postgres/kvtypes/hash/expire.d.ts +5 -0
  24. package/build/services/store/providers/postgres/kvtypes/hash/expire.js +33 -0
  25. package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +29 -0
  26. package/build/services/store/providers/postgres/kvtypes/hash/index.js +190 -0
  27. package/build/services/store/providers/postgres/kvtypes/hash/jsonb.d.ts +14 -0
  28. package/build/services/store/providers/postgres/kvtypes/hash/jsonb.js +699 -0
  29. package/build/services/store/providers/postgres/kvtypes/hash/scan.d.ts +10 -0
  30. package/build/services/store/providers/postgres/kvtypes/hash/scan.js +91 -0
  31. package/build/services/store/providers/postgres/kvtypes/hash/types.d.ts +19 -0
  32. package/build/services/store/providers/postgres/kvtypes/hash/types.js +2 -0
  33. package/build/services/store/providers/postgres/kvtypes/hash/utils.d.ts +18 -0
  34. package/build/services/store/providers/postgres/kvtypes/hash/utils.js +90 -0
  35. package/build/types/memflow.d.ts +1 -1
  36. package/build/types/meshdata.d.ts +1 -1
  37. package/package.json +16 -14
  38. package/build/services/store/providers/postgres/kvtypes/hash.d.ts +0 -60
  39. package/build/services/store/providers/postgres/kvtypes/hash.js +0 -1287
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports._scan = exports._hscan = exports.createScanOperations = void 0;
4
+ function createScanOperations(context) {
5
+ return {
6
+ async hscan(key, cursor, count = 10, pattern, multi) {
7
+ const { sql, params } = _hscan(context, key, cursor, count, pattern);
8
+ if (multi) {
9
+ multi.addCommand(sql, params, 'object', (rows) => {
10
+ const items = {};
11
+ for (const row of rows) {
12
+ items[row.field] = row.value;
13
+ }
14
+ const newCursor = rows.length < count ? 0 : Number(cursor) + rows.length;
15
+ return { cursor: newCursor.toString(), items };
16
+ });
17
+ return Promise.resolve({ cursor: '0', items: {} });
18
+ }
19
+ else {
20
+ const res = await context.pgClient.query(sql, params);
21
+ const items = {};
22
+ for (const row of res.rows) {
23
+ items[row.field] = row.value;
24
+ }
25
+ const newCursor = res.rowCount < count ? 0 : Number(cursor) + res.rowCount;
26
+ return { cursor: newCursor.toString(), items };
27
+ }
28
+ },
29
+ async scan(cursor, count = 10, pattern, multi) {
30
+ const { sql, params } = _scan(context, cursor, count, pattern);
31
+ if (multi) {
32
+ multi.addCommand(sql, params, 'object', (rows) => {
33
+ const keys = rows.map((row) => row.key);
34
+ const newCursor = cursor + rows.length;
35
+ return { cursor: newCursor, keys };
36
+ });
37
+ return Promise.resolve({ cursor: 0, keys: [] });
38
+ }
39
+ else {
40
+ const res = await context.pgClient.query(sql, params);
41
+ const keys = res.rows.map((row) => row.key);
42
+ const newCursor = cursor + res.rowCount;
43
+ return { cursor: newCursor, keys };
44
+ }
45
+ },
46
+ };
47
+ }
48
+ exports.createScanOperations = createScanOperations;
49
+ function _hscan(context, key, cursor, count, pattern) {
50
+ const tableName = context.tableForKey(key, 'hash');
51
+ const params = [key];
52
+ let sql = `
53
+ SELECT field, value FROM ${tableName}
54
+ WHERE key = $1 AND (expiry IS NULL OR expiry > NOW())
55
+ `;
56
+ let paramIndex = 2;
57
+ if (pattern) {
58
+ const sqlPattern = pattern.replace(/\*/g, '%');
59
+ sql += ` AND field LIKE $${paramIndex}`;
60
+ params.push(sqlPattern);
61
+ paramIndex++;
62
+ }
63
+ sql += `
64
+ ORDER BY field
65
+ OFFSET $${paramIndex} LIMIT $${paramIndex + 1}
66
+ `;
67
+ params.push(cursor.toString());
68
+ params.push(count.toString());
69
+ return { sql, params };
70
+ }
71
+ exports._hscan = _hscan;
72
+ function _scan(context, cursor, count, pattern) {
73
+ const tableName = context.tableForKey(`_:${context.appId}:j:_`);
74
+ let sql = `
75
+ SELECT key FROM ${tableName}
76
+ WHERE (expired_at IS NULL OR expired_at > NOW())
77
+ `;
78
+ const params = [];
79
+ if (pattern) {
80
+ sql += ' AND key LIKE $1';
81
+ params.push(pattern.replace(/\*/g, '%'));
82
+ }
83
+ sql += `
84
+ ORDER BY key
85
+ OFFSET $${params.length + 1} LIMIT $${params.length + 2}
86
+ `;
87
+ params.push(cursor.toString());
88
+ params.push(count.toString());
89
+ return { sql, params };
90
+ }
91
+ exports._scan = _scan;
@@ -0,0 +1,19 @@
1
+ import { PostgresJobEnumType } from '../../../../../../types/postgres';
2
+ import { HScanResult, HSetOptions, ProviderTransaction, SetOptions } from '../../../../../../types/provider';
3
+ import type { KVSQL } from '../../kvsql';
4
+ export interface Multi extends ProviderTransaction {
5
+ addCommand: (sql: string, params: any[], returnType: string, transform?: (rows: any[]) => any) => void;
6
+ }
7
+ export interface HashContext {
8
+ context: KVSQL;
9
+ }
10
+ export interface SqlResult {
11
+ sql: string;
12
+ params: any[];
13
+ }
14
+ export interface JsonbOperation {
15
+ path?: string;
16
+ value?: any;
17
+ index?: number;
18
+ }
19
+ export { PostgresJobEnumType, HScanResult, HSetOptions, ProviderTransaction, SetOptions, KVSQL, };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,18 @@
1
+ import { PostgresJobEnumType } from './types';
2
+ /**
3
+ * Determines if a table name represents a jobs table
4
+ */
5
+ export declare function isJobsTable(tableName: string): boolean;
6
+ /**
7
+ * Derives the enumerated `type` value based on the field name when
8
+ * setting a field in a jobs table (a 'jobshash' table type).
9
+ */
10
+ export declare function deriveType(fieldName: string): PostgresJobEnumType;
11
+ /**
12
+ * Processes rows from hmget and hgetall queries to map status and context fields
13
+ */
14
+ export declare function processJobsRows(rows: any[], fields?: string[]): any;
15
+ /**
16
+ * Processes rows from regular (non-jobs) tables for hgetall
17
+ */
18
+ export declare function processRegularRows(rows: any[]): Record<string, string>;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.processRegularRows = exports.processJobsRows = exports.deriveType = exports.isJobsTable = void 0;
4
+ /**
5
+ * Determines if a table name represents a jobs table
6
+ */
7
+ function isJobsTable(tableName) {
8
+ return tableName.endsWith('jobs');
9
+ }
10
+ exports.isJobsTable = isJobsTable;
11
+ /**
12
+ * Derives the enumerated `type` value based on the field name when
13
+ * setting a field in a jobs table (a 'jobshash' table type).
14
+ */
15
+ function deriveType(fieldName) {
16
+ if (fieldName === ':') {
17
+ return 'status';
18
+ }
19
+ else if (fieldName.startsWith('_')) {
20
+ return 'udata';
21
+ }
22
+ else if (fieldName.startsWith('-')) {
23
+ return fieldName.includes(',') ? 'hmark' : 'jmark';
24
+ }
25
+ else if (fieldName.length === 3) {
26
+ return 'jdata';
27
+ }
28
+ else if (fieldName.includes(',')) {
29
+ return 'adata';
30
+ }
31
+ else {
32
+ return 'other';
33
+ }
34
+ }
35
+ exports.deriveType = deriveType;
36
+ /**
37
+ * Processes rows from hmget and hgetall queries to map status and context fields
38
+ */
39
+ function processJobsRows(rows, fields) {
40
+ let statusValue = null;
41
+ let contextValue = null;
42
+ const fieldValueMap = new Map();
43
+ for (const row of rows) {
44
+ if (row.field === 'status') {
45
+ statusValue = row.value;
46
+ fieldValueMap.set(':', row.value); // Map status to ':'
47
+ }
48
+ else if (row.field === 'context') {
49
+ contextValue = row.value;
50
+ fieldValueMap.set('@', row.value); // Map context to '@'
51
+ }
52
+ else if (row.field !== ':' && row.field !== '@') {
53
+ // Ignore old format fields
54
+ fieldValueMap.set(row.field, row.value);
55
+ }
56
+ }
57
+ // Ensure ':' and '@' are present in the map with their values
58
+ if (statusValue !== null) {
59
+ fieldValueMap.set(':', statusValue);
60
+ }
61
+ if (contextValue !== null) {
62
+ fieldValueMap.set('@', contextValue);
63
+ }
64
+ if (fields) {
65
+ // For hmget - return array in same order as requested fields
66
+ return fields.map((field) => fieldValueMap.get(field) || null);
67
+ }
68
+ else {
69
+ // For hgetall - return object with all fields
70
+ const result = {};
71
+ for (const [field, value] of fieldValueMap) {
72
+ if (value !== null) {
73
+ result[field] = value;
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ }
79
+ exports.processJobsRows = processJobsRows;
80
+ /**
81
+ * Processes rows from regular (non-jobs) tables for hgetall
82
+ */
83
+ function processRegularRows(rows) {
84
+ const result = {};
85
+ for (const row of rows) {
86
+ result[row.field] = row.value;
87
+ }
88
+ return result;
89
+ }
90
+ exports.processRegularRows = processRegularRows;
@@ -264,7 +264,7 @@ type WorkflowOptions = {
264
264
  */
265
265
  config?: WorkflowConfig;
266
266
  /**
267
- * sets the number of seconds a workflow may exist after completion. As the process engine is an in-memory cache, the default policy is to expire and scrub the job hash as soon as it completes.
267
+ * sets the number of seconds a workflow may exist after completion. The default policy is to expire the job hash as soon as it completes.
268
268
  */
269
269
  expire?: number;
270
270
  /**
@@ -233,7 +233,7 @@ export type MeshDataWorkflowOptions = {
233
233
  */
234
234
  pending?: number;
235
235
  /**
236
- * sets the number of seconds a workflow may exist after completion. As the process engine is an in-memory cache, the default policy is to expire and scrub the job hash as soon as it completes.
236
+ * sets the number of seconds a workflow may exist after completion. The default policy is to expire the job hash as soon as it completes.
237
237
  * @default 1
238
238
  */
239
239
  expire?: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/hotmesh",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Permanent-Memory Workflows & AI Agents",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -27,26 +27,27 @@
27
27
  "test:connect:postgres": "NODE_ENV=test jest ./tests/unit/services/connector/providers/postgres.test.ts --detectOpenHandles --forceExit --verbose",
28
28
  "test:connect:redis": "NODE_ENV=test jest ./tests/unit/services/connector/providers/redis.test.ts --detectOpenHandles --forceExit --verbose",
29
29
  "test:connect:nats": "NODE_ENV=test jest ./tests/unit/services/connector/providers/nats.test.ts --detectOpenHandles --forceExit --verbose",
30
- "test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/*.test.ts --detectOpenHandles --forceExit --verbose",
31
- "test:memflow": "NODE_ENV=test jest ./tests/memflow/*/*.test.ts --detectOpenHandles --forceExit --verbose",
30
+ "test:memflow": "NODE_ENV=test jest ./tests/memflow/*/postgres.test.ts --detectOpenHandles --forceExit --verbose",
32
31
  "test:memflow:basic": "HMSH_LOGLEVEL=info NODE_ENV=test jest ./tests/memflow/basic/postgres.test.ts --detectOpenHandles --forceExit --verbose",
33
32
  "test:memflow:collision": "NODE_ENV=test jest ./tests/memflow/collision/*.test.ts --detectOpenHandles --forceExit --verbose",
34
33
  "test:memflow:fatal": "NODE_ENV=test jest ./tests/memflow/fatal/*.test.ts --detectOpenHandles --forceExit --verbose",
35
34
  "test:memflow:goodbye": "NODE_ENV=test jest ./tests/memflow/goodbye/*.test.ts --detectOpenHandles --forceExit --verbose",
36
35
  "test:memflow:entity": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/entity/postgres.test.ts --detectOpenHandles --forceExit --verbose",
37
36
  "test:memflow:agent": "NODE_ENV=test HMSH_LOGLEVEL=debug jest ./tests/memflow/agent/postgres.test.ts --detectOpenHandles --forceExit --verbose",
38
- "test:memflow:hello": "HMSH_TELEMETRY=debug HMSH_LOGLEVEL=debug HMSH_IS_CLUSTER=true NODE_ENV=test jest ./tests/memflow/helloworld/*.test.ts --detectOpenHandles --forceExit --verbose",
39
- "test:memflow:hook": "NODE_ENV=test jest ./tests/memflow/hook/*.test.ts --detectOpenHandles --forceExit --verbose",
40
- "test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
41
- "test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity/*.test.ts --detectOpenHandles --forceExit --verbose",
42
- "test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested/*.test.ts --detectOpenHandles --forceExit --verbose",
43
- "test:memflow:retry": "NODE_ENV=test jest ./tests/memflow/retry/*.test.ts --detectOpenHandles --forceExit --verbose",
44
- "test:memflow:sleep": "NODE_ENV=test jest ./tests/memflow/sleep/*.test.ts --detectOpenHandles --forceExit --verbose",
45
- "test:memflow:signal": "NODE_ENV=test jest ./tests/memflow/signal/*.test.ts --detectOpenHandles --forceExit --verbose",
46
- "test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/*.test.ts --detectOpenHandles --forceExit --verbose",
37
+ "test:memflow:hello": "HMSH_TELEMETRY=debug HMSH_LOGLEVEL=debug HMSH_IS_CLUSTER=true NODE_ENV=test jest ./tests/memflow/helloworld/postgres.test.ts --detectOpenHandles --forceExit --verbose",
38
+ "test:memflow:hook": "NODE_ENV=test jest ./tests/memflow/hook/postgres.test.ts --detectOpenHandles --forceExit --verbose",
39
+ "test:memflow:interrupt": "NODE_ENV=test jest ./tests/memflow/interrupt/postgres.test.ts --detectOpenHandles --forceExit --verbose",
40
+ "test:memflow:loopactivity": "NODE_ENV=test jest ./tests/memflow/loopactivity/postgres.test.ts --detectOpenHandles --forceExit --verbose",
41
+ "test:memflow:nested": "NODE_ENV=test jest ./tests/memflow/nested/postgres.test.ts --detectOpenHandles --forceExit --verbose",
42
+ "test:memflow:pipeline": "NODE_ENV=test jest ./tests/memflow/pipeline/postgres.test.ts --detectOpenHandles --forceExit --verbose",
43
+ "test:memflow:retry": "NODE_ENV=test jest ./tests/memflow/retry/postgres.test.ts --detectOpenHandles --forceExit --verbose",
44
+ "test:memflow:sleep": "NODE_ENV=test jest ./tests/memflow/sleep/postgres.test.ts --detectOpenHandles --forceExit --verbose",
45
+ "test:memflow:signal": "NODE_ENV=test jest ./tests/memflow/signal/postgres.test.ts --detectOpenHandles --forceExit --verbose",
46
+ "test:memflow:unknown": "NODE_ENV=test jest ./tests/memflow/unknown/postgres.test.ts --detectOpenHandles --forceExit --verbose",
47
+ "test:cycle": "NODE_ENV=test jest ./tests/functional/cycle/*.test.ts --detectOpenHandles --forceExit --verbose",
48
+ "test:functional": "NODE_ENV=test jest ./tests/functional/* --detectOpenHandles --forceExit --verbose",
47
49
  "test:emit": "NODE_ENV=test jest ./tests/functional/emit/*.test.ts --detectOpenHandles --forceExit --verbose",
48
50
  "test:pending": "NODE_ENV=test jest ./tests/functional/pending/index.test.ts --detectOpenHandles --forceExit --verbose",
49
- "test:functional": "NODE_ENV=test jest ./tests/functional/* --detectOpenHandles --forceExit --verbose",
50
51
  "test:hmsh": "NODE_ENV=test jest ./tests/functional/*.test.ts --detectOpenHandles --verbose --forceExit",
51
52
  "test:hook": "NODE_ENV=test jest ./tests/functional/hook/index.test.ts --detectOpenHandles --forceExit --verbose",
52
53
  "test:interrupt": "NODE_ENV=test jest ./tests/functional/interrupt/*.test.ts --detectOpenHandles --forceExit --verbose",
@@ -74,7 +75,6 @@
74
75
  "test:sub:postgres": "NODE_ENV=test jest ./tests/functional/sub/providers/postgres/postgres.test.ts --detectOpenHandles --forceExit --verbose",
75
76
  "test:sub:nats": "NODE_ENV=test jest ./tests/functional/sub/providers/nats/nats.test.ts --detectOpenHandles --forceExit --verbose",
76
77
  "test:trigger": "NODE_ENV=test jest ./tests/unit/services/activities/trigger.test.ts --detectOpenHandles --forceExit --verbose",
77
- "test:meshdata": "NODE_ENV=test jest ./tests/meshdata/postgres.test.ts --forceExit --verbose --detectOpenHandles",
78
78
  "test:meshos": "HMSH_LOGLEVEL=info NODE_ENV=test HMSH_IS_CLUSTER=true jest ./tests/meshos/*.test.ts --forceExit --verbose --detectOpenHandles",
79
79
  "test:meshcall": "NODE_ENV=test jest ./tests/meshcall/*.test.ts --forceExit --verbose --detectOpenHandles",
80
80
  "test:unit": "NODE_ENV=test jest ./tests/unit/*/*/index.test.ts --detectOpenHandles --forceExit --verbose"
@@ -109,6 +109,7 @@
109
109
  "@types/pg": "^8.10.0",
110
110
  "@typescript-eslint/eslint-plugin": "^5.62.0",
111
111
  "@typescript-eslint/parser": "^5.62.0",
112
+ "dotenv": "^16.3.1",
112
113
  "eslint": "^8.57.0",
113
114
  "eslint-config-prettier": "^9.1.0",
114
115
  "eslint-plugin-import": "^2.29.1",
@@ -117,6 +118,7 @@
117
118
  "javascript-obfuscator": "^4.1.1",
118
119
  "jest": "^29.5.0",
119
120
  "nats": "^2.28.0",
121
+ "openai": "^5.9.0",
120
122
  "pg": "^8.10.0",
121
123
  "redis": "^4.6.13",
122
124
  "rimraf": "^4.4.1",
@@ -1,60 +0,0 @@
1
- import { PostgresJobEnumType } from '../../../../../types/postgres';
2
- import { HScanResult, HSetOptions, ProviderTransaction } from '../../../../../types/provider';
3
- import type { KVSQL } from '../kvsql';
4
- export declare const hashModule: (context: KVSQL) => {
5
- hsetnx(key: string, field: string, value: string, multi?: ProviderTransaction, entity?: string): Promise<number>;
6
- hset(key: string, fields: Record<string, string>, options?: HSetOptions, multi?: ProviderTransaction): Promise<number | any>;
7
- /**
8
- * Derives the enumerated `type` value based on the field name when
9
- * setting a field in a jobs table (a 'jobshash' table type).
10
- */
11
- _deriveType(fieldName: string): PostgresJobEnumType;
12
- _hset(key: string, fields: Record<string, string>, options?: HSetOptions): {
13
- sql: string;
14
- params: any[];
15
- };
16
- hget(key: string, field: string, multi?: ProviderTransaction): Promise<string | null>;
17
- _hget(key: string, field: string): {
18
- sql: string;
19
- params: any[];
20
- };
21
- hdel(key: string, fields: string[], multi?: unknown): Promise<number>;
22
- _hdel(key: string, fields: string[]): {
23
- sql: string;
24
- params: any[];
25
- };
26
- hmget(key: string, fields: string[], multi?: ProviderTransaction): Promise<(string | null)[]>;
27
- _hmget(key: string, fields: string[]): {
28
- sql: string;
29
- params: any[];
30
- };
31
- hgetall(key: string, multi?: ProviderTransaction): Promise<Record<string, string>>;
32
- _hgetall(key: string): {
33
- sql: string;
34
- params: any[];
35
- };
36
- hincrbyfloat(key: string, field: string, increment: number, multi?: ProviderTransaction): Promise<number>;
37
- _hincrbyfloat(key: string, field: string, increment: number): {
38
- sql: string;
39
- params: any[];
40
- };
41
- hscan(key: string, cursor: string, count?: number, pattern?: string, multi?: ProviderTransaction): Promise<HScanResult>;
42
- _hscan(key: string, cursor: string, count: number, pattern?: string): {
43
- sql: string;
44
- params: any[];
45
- };
46
- expire(key: string, seconds: number, multi?: ProviderTransaction): Promise<boolean>;
47
- _expire(key: string, seconds: number): {
48
- sql: string;
49
- params: any[];
50
- };
51
- scan(cursor: number, count?: number, pattern?: string, multi?: ProviderTransaction): Promise<{
52
- cursor: number;
53
- keys: string[];
54
- }>;
55
- _scan(cursor: number, count: number, pattern?: string): {
56
- sql: string;
57
- params: any[];
58
- };
59
- isJobsTable(tableName: string): boolean;
60
- };