@majkapp/majk-chat-sessions 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.
- package/README.md +127 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/session-manager.d.ts +33 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +137 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/storage/filesystem.d.ts +24 -0
- package/dist/storage/filesystem.d.ts.map +1 -0
- package/dist/storage/filesystem.js +248 -0
- package/dist/storage/filesystem.js.map +1 -0
- package/dist/types/session.d.ts +40 -0
- package/dist/types/session.d.ts.map +1 -0
- package/dist/types/session.js +3 -0
- package/dist/types/session.js.map +1 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Magic Chat Sessions
|
|
2
|
+
|
|
3
|
+
Session management for Magic Chat conversations. This package provides persistent conversation storage and retrieval capabilities.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Persistent Sessions**: Store complete conversation histories with metadata
|
|
8
|
+
- **Working Directory Organization**: Sessions are organized by the working directory where they were created
|
|
9
|
+
- **Automatic Cleanup**: Configurable session cleanup based on age and count limits
|
|
10
|
+
- **UUID-based Session IDs**: Each session has a unique identifier for easy reference
|
|
11
|
+
- **Flexible Storage**: Pluggable storage interface with filesystem implementation
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Basic Session Management
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { SessionManager } from '@majkapp/majk-chat-sessions';
|
|
19
|
+
|
|
20
|
+
const sessionManager = new SessionManager();
|
|
21
|
+
|
|
22
|
+
// Create a new session
|
|
23
|
+
const sessionId = await sessionManager.createSession('/path/to/project', {
|
|
24
|
+
title: 'My Chat Session',
|
|
25
|
+
provider: 'openai',
|
|
26
|
+
model: 'gpt-4',
|
|
27
|
+
initialMessages: []
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Add messages to the session
|
|
31
|
+
await sessionManager.addMessage({
|
|
32
|
+
role: 'user',
|
|
33
|
+
content: 'Hello, how are you?'
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Continue the most recent session in a directory
|
|
37
|
+
const sessionData = await sessionManager.continueLatestSession('/path/to/project');
|
|
38
|
+
|
|
39
|
+
// Load a specific session
|
|
40
|
+
const sessionData = await sessionManager.loadSession(sessionId, '/path/to/project');
|
|
41
|
+
|
|
42
|
+
// List all sessions in a directory
|
|
43
|
+
const sessions = await sessionManager.listSessions('/path/to/project');
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### CLI Integration
|
|
47
|
+
|
|
48
|
+
The sessions package is integrated into the Magic Chat CLI with the following flags:
|
|
49
|
+
|
|
50
|
+
- `--continue`: Continue the most recent session in the current directory
|
|
51
|
+
- `--session <uuid>`: Continue a specific session by UUID
|
|
52
|
+
- `--session-title <title>`: Set a title for new sessions
|
|
53
|
+
- `--list-sessions`: List all sessions in the current directory
|
|
54
|
+
- `--delete-session <uuid>`: Delete a specific session
|
|
55
|
+
|
|
56
|
+
### Directory Organization
|
|
57
|
+
|
|
58
|
+
Sessions are stored in `~/.majk/chat-sessions/` organized by sanitized working directory names:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
~/.majk/chat-sessions/
|
|
62
|
+
├── home_user_projects_myapp/
|
|
63
|
+
│ ├── 550e8400-e29b-41d4-a716-446655440000.json
|
|
64
|
+
│ └── 6ba7b810-9dad-11d1-80b4-00c04fd430c8.json
|
|
65
|
+
└── home_user_documents/
|
|
66
|
+
└── f47ac10b-58cc-4372-a567-0e02b2c3d479.json
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
import { SessionManager, FileSystemSessionStorage } from '@majkapp/majk-chat-sessions';
|
|
73
|
+
|
|
74
|
+
const sessionManager = new SessionManager({
|
|
75
|
+
baseDirectory: '/custom/sessions/path', // Default: ~/.majk/chat-sessions
|
|
76
|
+
maxSessions: 500, // Default: 1000
|
|
77
|
+
autoCleanup: true, // Default: true
|
|
78
|
+
cleanupAfterDays: 30 // Default: 90
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Custom Storage
|
|
83
|
+
|
|
84
|
+
You can implement custom storage backends by implementing the `SessionStorage` interface:
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { SessionStorage, SessionData, SessionListItem } from '@majkapp/majk-chat-sessions';
|
|
88
|
+
|
|
89
|
+
class CustomStorage implements SessionStorage {
|
|
90
|
+
async save(sessionData: SessionData): Promise<void> {
|
|
91
|
+
// Your implementation
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async load(sessionId: string, workingDirectory: string): Promise<SessionData | null> {
|
|
95
|
+
// Your implementation
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ... implement other methods
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const sessionManager = new SessionManager({
|
|
102
|
+
storage: new CustomStorage()
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Session Data Structure
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
interface SessionData {
|
|
110
|
+
metadata: {
|
|
111
|
+
id: string;
|
|
112
|
+
workingDirectory: string;
|
|
113
|
+
createdAt: Date;
|
|
114
|
+
updatedAt: Date;
|
|
115
|
+
title?: string;
|
|
116
|
+
provider?: string;
|
|
117
|
+
model?: string;
|
|
118
|
+
totalMessages: number;
|
|
119
|
+
};
|
|
120
|
+
messages: Message[]; // Array of chat messages
|
|
121
|
+
context?: Record<string, any>; // Additional context data
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { SessionManager } from './session-manager';
|
|
2
|
+
export { FileSystemSessionStorage } from './storage/filesystem';
|
|
3
|
+
export { SessionMetadata, SessionData, SessionListItem, SessionStorageConfig, SessionStorage } from './types/session';
|
|
4
|
+
export { SessionManagerConfig } from './session-manager';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EACL,eAAe,EACf,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,cAAc,EACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FileSystemSessionStorage = exports.SessionManager = void 0;
|
|
4
|
+
var session_manager_1 = require("./session-manager");
|
|
5
|
+
Object.defineProperty(exports, "SessionManager", { enumerable: true, get: function () { return session_manager_1.SessionManager; } });
|
|
6
|
+
var filesystem_1 = require("./storage/filesystem");
|
|
7
|
+
Object.defineProperty(exports, "FileSystemSessionStorage", { enumerable: true, get: function () { return filesystem_1.FileSystemSessionStorage; } });
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qDAAmD;AAA1C,iHAAA,cAAc,OAAA;AACvB,mDAAgE;AAAvD,sHAAA,wBAAwB,OAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Message } from '@majkapp/majk-chat-core';
|
|
2
|
+
import { SessionStorage, SessionData, SessionMetadata, SessionListItem, SessionStorageConfig } from './types/session';
|
|
3
|
+
export interface SessionManagerConfig extends SessionStorageConfig {
|
|
4
|
+
storage?: SessionStorage;
|
|
5
|
+
}
|
|
6
|
+
export declare class SessionManager {
|
|
7
|
+
private storage;
|
|
8
|
+
private currentSession;
|
|
9
|
+
constructor(config?: SessionManagerConfig);
|
|
10
|
+
createSession(workingDirectory: string, options?: {
|
|
11
|
+
title?: string;
|
|
12
|
+
provider?: string;
|
|
13
|
+
model?: string;
|
|
14
|
+
initialMessages?: Message[];
|
|
15
|
+
context?: Record<string, any>;
|
|
16
|
+
}): Promise<string>;
|
|
17
|
+
loadSession(sessionId: string, workingDirectory: string): Promise<SessionData | null>;
|
|
18
|
+
continueLatestSession(workingDirectory: string): Promise<SessionData | null>;
|
|
19
|
+
addMessage(message: Message): Promise<void>;
|
|
20
|
+
addMessages(messages: Message[]): Promise<void>;
|
|
21
|
+
updateSessionMetadata(updates: Partial<SessionMetadata>): Promise<void>;
|
|
22
|
+
updateSessionContext(context: Record<string, any>): Promise<void>;
|
|
23
|
+
getCurrentSession(): SessionData | null;
|
|
24
|
+
getCurrentSessionId(): string | null;
|
|
25
|
+
getMessages(): Message[];
|
|
26
|
+
listSessions(workingDirectory: string): Promise<SessionListItem[]>;
|
|
27
|
+
deleteSession(sessionId: string, workingDirectory: string): Promise<boolean>;
|
|
28
|
+
sessionExists(sessionId: string, workingDirectory: string): Promise<boolean>;
|
|
29
|
+
cleanup(workingDirectory?: string): Promise<number>;
|
|
30
|
+
clearCurrentSession(): void;
|
|
31
|
+
generateSessionTitle(maxLength?: number): Promise<string | null>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAGtH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,cAAc,CAA4B;gBAEtC,MAAM,GAAE,oBAAyB;IAIvC,aAAa,CACjB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;QAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;KAC1B,GACL,OAAO,CAAC,MAAM,CAAC;IA2BZ,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAUrF,qBAAqB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAU5E,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3C,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/C,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvE,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IASvE,iBAAiB,IAAI,WAAW,GAAG,IAAI;IAIvC,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC,WAAW,IAAI,OAAO,EAAE;IAIlB,YAAY,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAIlE,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU5E,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI5E,OAAO,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzD,mBAAmB,IAAI,IAAI;IAIrB,oBAAoB,CAAC,SAAS,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CA+B3E"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SessionManager = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const filesystem_1 = require("./storage/filesystem");
|
|
6
|
+
class SessionManager {
|
|
7
|
+
constructor(config = {}) {
|
|
8
|
+
this.currentSession = null;
|
|
9
|
+
this.storage = config.storage || new filesystem_1.FileSystemSessionStorage(config);
|
|
10
|
+
}
|
|
11
|
+
async createSession(workingDirectory, options = {}) {
|
|
12
|
+
const sessionId = (0, uuid_1.v4)();
|
|
13
|
+
const now = new Date();
|
|
14
|
+
const metadata = {
|
|
15
|
+
id: sessionId,
|
|
16
|
+
workingDirectory,
|
|
17
|
+
createdAt: now,
|
|
18
|
+
updatedAt: now,
|
|
19
|
+
title: options.title,
|
|
20
|
+
provider: options.provider,
|
|
21
|
+
model: options.model,
|
|
22
|
+
totalMessages: options.initialMessages?.length || 0
|
|
23
|
+
};
|
|
24
|
+
const sessionData = {
|
|
25
|
+
metadata,
|
|
26
|
+
messages: options.initialMessages || [],
|
|
27
|
+
context: options.context
|
|
28
|
+
};
|
|
29
|
+
await this.storage.save(sessionData);
|
|
30
|
+
this.currentSession = sessionData;
|
|
31
|
+
return sessionId;
|
|
32
|
+
}
|
|
33
|
+
async loadSession(sessionId, workingDirectory) {
|
|
34
|
+
const sessionData = await this.storage.load(sessionId, workingDirectory);
|
|
35
|
+
if (sessionData) {
|
|
36
|
+
this.currentSession = sessionData;
|
|
37
|
+
}
|
|
38
|
+
return sessionData;
|
|
39
|
+
}
|
|
40
|
+
async continueLatestSession(workingDirectory) {
|
|
41
|
+
const sessionData = await this.storage.getLatest(workingDirectory);
|
|
42
|
+
if (sessionData) {
|
|
43
|
+
this.currentSession = sessionData;
|
|
44
|
+
}
|
|
45
|
+
return sessionData;
|
|
46
|
+
}
|
|
47
|
+
async addMessage(message) {
|
|
48
|
+
if (!this.currentSession) {
|
|
49
|
+
throw new Error('No active session. Create or load a session first.');
|
|
50
|
+
}
|
|
51
|
+
this.currentSession.messages.push(message);
|
|
52
|
+
this.currentSession.metadata.totalMessages = this.currentSession.messages.length;
|
|
53
|
+
this.currentSession.metadata.updatedAt = new Date();
|
|
54
|
+
await this.storage.save(this.currentSession);
|
|
55
|
+
}
|
|
56
|
+
async addMessages(messages) {
|
|
57
|
+
if (!this.currentSession) {
|
|
58
|
+
throw new Error('No active session. Create or load a session first.');
|
|
59
|
+
}
|
|
60
|
+
this.currentSession.messages.push(...messages);
|
|
61
|
+
this.currentSession.metadata.totalMessages = this.currentSession.messages.length;
|
|
62
|
+
this.currentSession.metadata.updatedAt = new Date();
|
|
63
|
+
await this.storage.save(this.currentSession);
|
|
64
|
+
}
|
|
65
|
+
async updateSessionMetadata(updates) {
|
|
66
|
+
if (!this.currentSession) {
|
|
67
|
+
throw new Error('No active session. Create or load a session first.');
|
|
68
|
+
}
|
|
69
|
+
Object.assign(this.currentSession.metadata, updates);
|
|
70
|
+
this.currentSession.metadata.updatedAt = new Date();
|
|
71
|
+
await this.storage.save(this.currentSession);
|
|
72
|
+
}
|
|
73
|
+
async updateSessionContext(context) {
|
|
74
|
+
if (!this.currentSession) {
|
|
75
|
+
throw new Error('No active session. Create or load a session first.');
|
|
76
|
+
}
|
|
77
|
+
this.currentSession.context = { ...this.currentSession.context, ...context };
|
|
78
|
+
await this.storage.save(this.currentSession);
|
|
79
|
+
}
|
|
80
|
+
getCurrentSession() {
|
|
81
|
+
return this.currentSession;
|
|
82
|
+
}
|
|
83
|
+
getCurrentSessionId() {
|
|
84
|
+
return this.currentSession?.metadata.id || null;
|
|
85
|
+
}
|
|
86
|
+
getMessages() {
|
|
87
|
+
return this.currentSession?.messages || [];
|
|
88
|
+
}
|
|
89
|
+
async listSessions(workingDirectory) {
|
|
90
|
+
return await this.storage.list(workingDirectory);
|
|
91
|
+
}
|
|
92
|
+
async deleteSession(sessionId, workingDirectory) {
|
|
93
|
+
const deleted = await this.storage.delete(sessionId, workingDirectory);
|
|
94
|
+
if (deleted && this.currentSession?.metadata.id === sessionId) {
|
|
95
|
+
this.currentSession = null;
|
|
96
|
+
}
|
|
97
|
+
return deleted;
|
|
98
|
+
}
|
|
99
|
+
async sessionExists(sessionId, workingDirectory) {
|
|
100
|
+
return await this.storage.exists(sessionId, workingDirectory);
|
|
101
|
+
}
|
|
102
|
+
async cleanup(workingDirectory) {
|
|
103
|
+
return await this.storage.cleanup(workingDirectory);
|
|
104
|
+
}
|
|
105
|
+
clearCurrentSession() {
|
|
106
|
+
this.currentSession = null;
|
|
107
|
+
}
|
|
108
|
+
async generateSessionTitle(maxLength = 50) {
|
|
109
|
+
if (!this.currentSession || this.currentSession.messages.length === 0) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const firstUserMessage = this.currentSession.messages.find(m => m.role === 'user');
|
|
113
|
+
if (!firstUserMessage) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
let content = '';
|
|
117
|
+
if (typeof firstUserMessage.content === 'string') {
|
|
118
|
+
content = firstUserMessage.content;
|
|
119
|
+
}
|
|
120
|
+
else if (Array.isArray(firstUserMessage.content)) {
|
|
121
|
+
const textBlocks = firstUserMessage.content.filter(block => block.type === 'text');
|
|
122
|
+
if (textBlocks.length > 0) {
|
|
123
|
+
content = textBlocks[0].text;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (!content) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const title = content.length > maxLength
|
|
130
|
+
? content.substring(0, maxLength).trim() + '...'
|
|
131
|
+
: content.trim();
|
|
132
|
+
await this.updateSessionMetadata({ title });
|
|
133
|
+
return title;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.SessionManager = SessionManager;
|
|
137
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SessionStorage, SessionData, SessionListItem, SessionStorageConfig } from '../types/session';
|
|
2
|
+
export declare class FileSystemSessionStorage implements SessionStorage {
|
|
3
|
+
private baseDirectory;
|
|
4
|
+
private maxSessions;
|
|
5
|
+
private autoCleanup;
|
|
6
|
+
private cleanupAfterDays;
|
|
7
|
+
constructor(config?: SessionStorageConfig);
|
|
8
|
+
private sanitizeDirectoryName;
|
|
9
|
+
private getSessionDirectory;
|
|
10
|
+
private getSessionFilePath;
|
|
11
|
+
private ensureDirectoryExists;
|
|
12
|
+
private readSessionFile;
|
|
13
|
+
private writeSessionFile;
|
|
14
|
+
save(sessionData: SessionData): Promise<void>;
|
|
15
|
+
load(sessionId: string, workingDirectory: string): Promise<SessionData | null>;
|
|
16
|
+
exists(sessionId: string, workingDirectory: string): Promise<boolean>;
|
|
17
|
+
list(workingDirectory: string): Promise<SessionListItem[]>;
|
|
18
|
+
private extractLastMessageContent;
|
|
19
|
+
delete(sessionId: string, workingDirectory: string): Promise<boolean>;
|
|
20
|
+
getLatest(workingDirectory: string): Promise<SessionData | null>;
|
|
21
|
+
cleanup(workingDirectory?: string): Promise<number>;
|
|
22
|
+
private performCleanup;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=filesystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/storage/filesystem.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEtG,qBAAa,wBAAyB,YAAW,cAAc;IAC7D,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,GAAE,oBAAyB;IAO7C,OAAO,CAAC,qBAAqB;IAQ7B,OAAO,CAAC,mBAAmB;IAe3B,OAAO,CAAC,kBAAkB;YAIZ,qBAAqB;YAQrB,eAAe;YAiBf,gBAAgB;IASxB,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB7C,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAK9E,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUrE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IA+ChE,OAAO,CAAC,yBAAyB;IAkB3B,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAcrE,SAAS,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAWhE,OAAO,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAuB3C,cAAc;CA2B7B"}
|
|
@@ -0,0 +1,248 @@
|
|
|
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.FileSystemSessionStorage = void 0;
|
|
37
|
+
const fs = __importStar(require("fs/promises"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
class FileSystemSessionStorage {
|
|
41
|
+
constructor(config = {}) {
|
|
42
|
+
this.baseDirectory = config.baseDirectory || path.join(os.homedir(), '.majk', 'chat-sessions');
|
|
43
|
+
this.maxSessions = config.maxSessions || 1000;
|
|
44
|
+
this.autoCleanup = config.autoCleanup ?? true;
|
|
45
|
+
this.cleanupAfterDays = config.cleanupAfterDays || 90;
|
|
46
|
+
}
|
|
47
|
+
sanitizeDirectoryName(dirPath) {
|
|
48
|
+
return dirPath
|
|
49
|
+
.replace(/^\/+|\/+$/g, '')
|
|
50
|
+
.replace(/[^a-zA-Z0-9_\-]/g, '_')
|
|
51
|
+
.replace(/_+/g, '_')
|
|
52
|
+
.toLowerCase();
|
|
53
|
+
}
|
|
54
|
+
getSessionDirectory(workingDirectory) {
|
|
55
|
+
const sanitizedName = this.sanitizeDirectoryName(workingDirectory);
|
|
56
|
+
const homeSanitized = this.sanitizeDirectoryName(os.homedir());
|
|
57
|
+
let sessionDirName;
|
|
58
|
+
if (workingDirectory.startsWith(os.homedir())) {
|
|
59
|
+
const relativePath = path.relative(os.homedir(), workingDirectory);
|
|
60
|
+
sessionDirName = `home_${this.sanitizeDirectoryName(relativePath)}`;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
sessionDirName = sanitizedName;
|
|
64
|
+
}
|
|
65
|
+
return path.join(this.baseDirectory, sessionDirName);
|
|
66
|
+
}
|
|
67
|
+
getSessionFilePath(sessionId, workingDirectory) {
|
|
68
|
+
return path.join(this.getSessionDirectory(workingDirectory), `${sessionId}.json`);
|
|
69
|
+
}
|
|
70
|
+
async ensureDirectoryExists(dirPath) {
|
|
71
|
+
try {
|
|
72
|
+
await fs.access(dirPath);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async readSessionFile(filePath) {
|
|
79
|
+
try {
|
|
80
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
81
|
+
const data = JSON.parse(content);
|
|
82
|
+
data.metadata.createdAt = new Date(data.metadata.createdAt);
|
|
83
|
+
data.metadata.updatedAt = new Date(data.metadata.updatedAt);
|
|
84
|
+
return data;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
if (error.code === 'ENOENT') {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
throw new Error(`Failed to read session file: ${error}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async writeSessionFile(filePath, sessionData) {
|
|
94
|
+
try {
|
|
95
|
+
const content = JSON.stringify(sessionData, null, 2);
|
|
96
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
throw new Error(`Failed to write session file: ${error}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async save(sessionData) {
|
|
103
|
+
const sessionDir = this.getSessionDirectory(sessionData.metadata.workingDirectory);
|
|
104
|
+
await this.ensureDirectoryExists(sessionDir);
|
|
105
|
+
const filePath = this.getSessionFilePath(sessionData.metadata.id, sessionData.metadata.workingDirectory);
|
|
106
|
+
sessionData.metadata.updatedAt = new Date();
|
|
107
|
+
sessionData.metadata.totalMessages = sessionData.messages.length;
|
|
108
|
+
await this.writeSessionFile(filePath, sessionData);
|
|
109
|
+
if (this.autoCleanup) {
|
|
110
|
+
await this.performCleanup(sessionData.metadata.workingDirectory);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async load(sessionId, workingDirectory) {
|
|
114
|
+
const filePath = this.getSessionFilePath(sessionId, workingDirectory);
|
|
115
|
+
return await this.readSessionFile(filePath);
|
|
116
|
+
}
|
|
117
|
+
async exists(sessionId, workingDirectory) {
|
|
118
|
+
const filePath = this.getSessionFilePath(sessionId, workingDirectory);
|
|
119
|
+
try {
|
|
120
|
+
await fs.access(filePath);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async list(workingDirectory) {
|
|
128
|
+
const sessionDir = this.getSessionDirectory(workingDirectory);
|
|
129
|
+
try {
|
|
130
|
+
await fs.access(sessionDir);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
const files = await fs.readdir(sessionDir);
|
|
137
|
+
const sessionFiles = files.filter(file => file.endsWith('.json'));
|
|
138
|
+
const sessions = [];
|
|
139
|
+
for (const file of sessionFiles) {
|
|
140
|
+
const filePath = path.join(sessionDir, file);
|
|
141
|
+
try {
|
|
142
|
+
const sessionData = await this.readSessionFile(filePath);
|
|
143
|
+
if (sessionData) {
|
|
144
|
+
const lastMessage = sessionData.messages.length > 0
|
|
145
|
+
? this.extractLastMessageContent(sessionData.messages[sessionData.messages.length - 1])
|
|
146
|
+
: undefined;
|
|
147
|
+
sessions.push({
|
|
148
|
+
id: sessionData.metadata.id,
|
|
149
|
+
title: sessionData.metadata.title,
|
|
150
|
+
createdAt: sessionData.metadata.createdAt,
|
|
151
|
+
updatedAt: sessionData.metadata.updatedAt,
|
|
152
|
+
totalMessages: sessionData.metadata.totalMessages,
|
|
153
|
+
lastMessage
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
// Skip corrupted or unreadable session files
|
|
159
|
+
console.warn(`Skipping corrupted session file: ${file}`);
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return sessions.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
throw new Error(`Failed to list sessions: ${error}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
extractLastMessageContent(message) {
|
|
170
|
+
if (typeof message.content === 'string') {
|
|
171
|
+
return message.content.length > 100
|
|
172
|
+
? message.content.substring(0, 100) + '...'
|
|
173
|
+
: message.content;
|
|
174
|
+
}
|
|
175
|
+
if (Array.isArray(message.content)) {
|
|
176
|
+
const textBlocks = message.content.filter((block) => block.type === 'text');
|
|
177
|
+
if (textBlocks.length > 0) {
|
|
178
|
+
const text = textBlocks[0].text;
|
|
179
|
+
return text.length > 100 ? text.substring(0, 100) + '...' : text;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return '[Complex content]';
|
|
183
|
+
}
|
|
184
|
+
async delete(sessionId, workingDirectory) {
|
|
185
|
+
const filePath = this.getSessionFilePath(sessionId, workingDirectory);
|
|
186
|
+
try {
|
|
187
|
+
await fs.unlink(filePath);
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (error.code === 'ENOENT') {
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
throw new Error(`Failed to delete session: ${error}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async getLatest(workingDirectory) {
|
|
198
|
+
const sessions = await this.list(workingDirectory);
|
|
199
|
+
if (sessions.length === 0) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const latest = sessions[0];
|
|
203
|
+
return await this.load(latest.id, workingDirectory);
|
|
204
|
+
}
|
|
205
|
+
async cleanup(workingDirectory) {
|
|
206
|
+
let cleanedUp = 0;
|
|
207
|
+
if (workingDirectory) {
|
|
208
|
+
cleanedUp += await this.performCleanup(workingDirectory);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
try {
|
|
212
|
+
const workingDirs = await fs.readdir(this.baseDirectory);
|
|
213
|
+
for (const dir of workingDirs) {
|
|
214
|
+
const fullPath = path.join(this.baseDirectory, dir);
|
|
215
|
+
const stats = await fs.stat(fullPath);
|
|
216
|
+
if (stats.isDirectory()) {
|
|
217
|
+
cleanedUp += await this.performCleanup(fullPath);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
// Ignore if base directory doesn't exist
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return cleanedUp;
|
|
226
|
+
}
|
|
227
|
+
async performCleanup(workingDirectory) {
|
|
228
|
+
const cutoffDate = new Date();
|
|
229
|
+
cutoffDate.setDate(cutoffDate.getDate() - this.cleanupAfterDays);
|
|
230
|
+
const sessions = await this.list(workingDirectory);
|
|
231
|
+
let cleanedUp = 0;
|
|
232
|
+
const sessionsToDelete = sessions.filter(session => session.updatedAt < cutoffDate);
|
|
233
|
+
if (sessions.length - sessionsToDelete.length > this.maxSessions) {
|
|
234
|
+
const excessSessions = sessions
|
|
235
|
+
.slice(this.maxSessions)
|
|
236
|
+
.filter(session => !sessionsToDelete.includes(session));
|
|
237
|
+
sessionsToDelete.push(...excessSessions);
|
|
238
|
+
}
|
|
239
|
+
for (const session of sessionsToDelete) {
|
|
240
|
+
if (await this.delete(session.id, workingDirectory)) {
|
|
241
|
+
cleanedUp++;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return cleanedUp;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
exports.FileSystemSessionStorage = FileSystemSessionStorage;
|
|
248
|
+
//# sourceMappingURL=filesystem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../src/storage/filesystem.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Message } from '@majkapp/majk-chat-core';
|
|
2
|
+
export interface SessionMetadata {
|
|
3
|
+
id: string;
|
|
4
|
+
workingDirectory: string;
|
|
5
|
+
createdAt: Date;
|
|
6
|
+
updatedAt: Date;
|
|
7
|
+
title?: string;
|
|
8
|
+
provider?: string;
|
|
9
|
+
model?: string;
|
|
10
|
+
totalMessages: number;
|
|
11
|
+
}
|
|
12
|
+
export interface SessionData {
|
|
13
|
+
metadata: SessionMetadata;
|
|
14
|
+
messages: Message[];
|
|
15
|
+
context?: Record<string, any>;
|
|
16
|
+
}
|
|
17
|
+
export interface SessionListItem {
|
|
18
|
+
id: string;
|
|
19
|
+
title?: string;
|
|
20
|
+
createdAt: Date;
|
|
21
|
+
updatedAt: Date;
|
|
22
|
+
totalMessages: number;
|
|
23
|
+
lastMessage?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SessionStorageConfig {
|
|
26
|
+
baseDirectory?: string;
|
|
27
|
+
maxSessions?: number;
|
|
28
|
+
autoCleanup?: boolean;
|
|
29
|
+
cleanupAfterDays?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface SessionStorage {
|
|
32
|
+
save(sessionData: SessionData): Promise<void>;
|
|
33
|
+
load(sessionId: string, workingDirectory: string): Promise<SessionData | null>;
|
|
34
|
+
exists(sessionId: string, workingDirectory: string): Promise<boolean>;
|
|
35
|
+
list(workingDirectory: string): Promise<SessionListItem[]>;
|
|
36
|
+
delete(sessionId: string, workingDirectory: string): Promise<boolean>;
|
|
37
|
+
getLatest(workingDirectory: string): Promise<SessionData | null>;
|
|
38
|
+
cleanup(workingDirectory?: string): Promise<number>;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/types/session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC/E,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC3D,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtE,SAAS,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACjE,OAAO,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/types/session.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@majkapp/majk-chat-sessions",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Session management for Magic Chat conversations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"test:watch": "jest --watch",
|
|
11
|
+
"clean": "rm -rf dist",
|
|
12
|
+
"prepare": "echo 'Use npm run build from root to build all packages'"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"majk-chat",
|
|
16
|
+
"sessions",
|
|
17
|
+
"conversation",
|
|
18
|
+
"storage"
|
|
19
|
+
],
|
|
20
|
+
"author": "Jules White",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@majkapp/majk-chat-core": "file:../majk-chat-core",
|
|
24
|
+
"uuid": "^9.0.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/jest": "^29.5.12",
|
|
28
|
+
"@types/node": "^20.14.0",
|
|
29
|
+
"@types/uuid": "^9.0.0",
|
|
30
|
+
"jest": "^29.7.0",
|
|
31
|
+
"ts-jest": "^29.1.5",
|
|
32
|
+
"typescript": "^5.5.0"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18.0.0"
|
|
36
|
+
},
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist/**/*",
|
|
42
|
+
"README.md"
|
|
43
|
+
]
|
|
44
|
+
}
|