@vybestack/llxprt-code-storage 0.10.0-nightly.260613.1adad3b34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.last_build +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/src/config/storage.d.ts +39 -0
- package/dist/src/config/storage.js +118 -0
- package/dist/src/config/storage.js.map +1 -0
- package/dist/src/conversation/ConversationFileWriter.d.ts +27 -0
- package/dist/src/conversation/ConversationFileWriter.js +78 -0
- package/dist/src/conversation/ConversationFileWriter.js.map +1 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/index.js +14 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/secure-store/provider-key-storage.d.ts +53 -0
- package/dist/src/secure-store/provider-key-storage.js +117 -0
- package/dist/src/secure-store/provider-key-storage.js.map +1 -0
- package/dist/src/secure-store/secure-store.d.ts +69 -0
- package/dist/src/secure-store/secure-store.js +606 -0
- package/dist/src/secure-store/secure-store.js.map +1 -0
- package/dist/src/services/fileDiscoveryService.d.ts +48 -0
- package/dist/src/services/fileDiscoveryService.js +154 -0
- package/dist/src/services/fileDiscoveryService.js.map +1 -0
- package/dist/src/services/fileSystemService.d.ts +33 -0
- package/dist/src/services/fileSystemService.js +25 -0
- package/dist/src/services/fileSystemService.js.map +1 -0
- package/dist/src/session/sessionTypes.d.ts +39 -0
- package/dist/src/session/sessionTypes.js +10 -0
- package/dist/src/session/sessionTypes.js.map +1 -0
- package/dist/src/testing.d.ts +1 -0
- package/dist/src/testing.js +4 -0
- package/dist/src/testing.js.map +1 -0
- package/dist/src/types/logger.d.ts +17 -0
- package/dist/src/types/logger.js +17 -0
- package/dist/src/types/logger.js.map +1 -0
- package/dist/src/utils/gitIgnoreParser.d.ts +29 -0
- package/dist/src/utils/gitIgnoreParser.js +199 -0
- package/dist/src/utils/gitIgnoreParser.js.map +1 -0
- package/dist/src/utils/gitUtils.d.ts +17 -0
- package/dist/src/utils/gitUtils.js +68 -0
- package/dist/src/utils/gitUtils.js.map +1 -0
- package/package.json +77 -0
package/dist/.last_build
ADDED
|
File without changes
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/index.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
export declare const LLXPRT_DIR = ".llxprt";
|
|
7
|
+
export declare const PROVIDER_ACCOUNTS_FILENAME = "provider_accounts.json";
|
|
8
|
+
export declare const OAUTH_FILE = "oauth_creds.json";
|
|
9
|
+
export declare class Storage {
|
|
10
|
+
private readonly targetDir;
|
|
11
|
+
constructor(targetDir: string);
|
|
12
|
+
static getGlobalLlxprtDir(): string;
|
|
13
|
+
static getMcpOAuthTokensPath(): string;
|
|
14
|
+
static getGlobalSettingsPath(): string;
|
|
15
|
+
static getInstallationIdPath(): string;
|
|
16
|
+
static getProviderAccountsPath(): string;
|
|
17
|
+
static getGoogleAccountsPath(): string;
|
|
18
|
+
static getUserCommandsDir(): string;
|
|
19
|
+
static getUserSkillsDir(): string;
|
|
20
|
+
static getGlobalMemoryFilePath(): string;
|
|
21
|
+
static getUserPoliciesDir(): string;
|
|
22
|
+
static getSystemSettingsPath(): string;
|
|
23
|
+
static getSystemPoliciesDir(): string;
|
|
24
|
+
static getGlobalTempDir(): string;
|
|
25
|
+
getLlxprtDir(): string;
|
|
26
|
+
getProjectTempDir(): string;
|
|
27
|
+
ensureProjectTempDirExists(): void;
|
|
28
|
+
static getOAuthCredsPath(): string;
|
|
29
|
+
getProjectRoot(): string;
|
|
30
|
+
private getFilePathHash;
|
|
31
|
+
getHistoryDir(): string;
|
|
32
|
+
getWorkspaceSettingsPath(): string;
|
|
33
|
+
getProjectCommandsDir(): string;
|
|
34
|
+
getProjectSkillsDir(): string;
|
|
35
|
+
getProjectTempCheckpointsDir(): string;
|
|
36
|
+
getExtensionsDir(): string;
|
|
37
|
+
getExtensionsConfigPath(): string;
|
|
38
|
+
getHistoryFilePath(): string;
|
|
39
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import * as os from 'os';
|
|
8
|
+
import * as crypto from 'crypto';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
export const LLXPRT_DIR = '.llxprt';
|
|
11
|
+
export const PROVIDER_ACCOUNTS_FILENAME = 'provider_accounts.json';
|
|
12
|
+
export const OAUTH_FILE = 'oauth_creds.json';
|
|
13
|
+
const TMP_DIR_NAME = 'tmp';
|
|
14
|
+
export class Storage {
|
|
15
|
+
targetDir;
|
|
16
|
+
constructor(targetDir) {
|
|
17
|
+
this.targetDir = targetDir;
|
|
18
|
+
}
|
|
19
|
+
static getGlobalLlxprtDir() {
|
|
20
|
+
const homeDir = os.homedir();
|
|
21
|
+
if (!homeDir) {
|
|
22
|
+
return path.join(os.tmpdir(), '.llxprt');
|
|
23
|
+
}
|
|
24
|
+
return path.join(homeDir, LLXPRT_DIR);
|
|
25
|
+
}
|
|
26
|
+
static getMcpOAuthTokensPath() {
|
|
27
|
+
return path.join(Storage.getGlobalLlxprtDir(), 'mcp-oauth-tokens.json');
|
|
28
|
+
}
|
|
29
|
+
static getGlobalSettingsPath() {
|
|
30
|
+
return path.join(Storage.getGlobalLlxprtDir(), 'settings.json');
|
|
31
|
+
}
|
|
32
|
+
static getInstallationIdPath() {
|
|
33
|
+
return path.join(Storage.getGlobalLlxprtDir(), 'installation_id');
|
|
34
|
+
}
|
|
35
|
+
static getProviderAccountsPath() {
|
|
36
|
+
return path.join(Storage.getGlobalLlxprtDir(), PROVIDER_ACCOUNTS_FILENAME);
|
|
37
|
+
}
|
|
38
|
+
static getGoogleAccountsPath() {
|
|
39
|
+
return path.join(Storage.getGlobalLlxprtDir(), 'google_accounts.json');
|
|
40
|
+
}
|
|
41
|
+
static getUserCommandsDir() {
|
|
42
|
+
return path.join(Storage.getGlobalLlxprtDir(), 'commands');
|
|
43
|
+
}
|
|
44
|
+
static getUserSkillsDir() {
|
|
45
|
+
return path.join(Storage.getGlobalTempDir(), 'skills');
|
|
46
|
+
}
|
|
47
|
+
static getGlobalMemoryFilePath() {
|
|
48
|
+
return path.join(Storage.getGlobalLlxprtDir(), 'memory.md');
|
|
49
|
+
}
|
|
50
|
+
static getUserPoliciesDir() {
|
|
51
|
+
return path.join(Storage.getGlobalLlxprtDir(), 'policies');
|
|
52
|
+
}
|
|
53
|
+
static getSystemSettingsPath() {
|
|
54
|
+
if (process.env['LLXPRT_SYSTEM_SETTINGS_PATH']) {
|
|
55
|
+
return process.env['LLXPRT_SYSTEM_SETTINGS_PATH'];
|
|
56
|
+
}
|
|
57
|
+
if (os.platform() === 'darwin') {
|
|
58
|
+
return '/Library/Application Support/LlxprtCode/settings.json';
|
|
59
|
+
}
|
|
60
|
+
else if (os.platform() === 'win32') {
|
|
61
|
+
return 'C:\\ProgramData\\llxprt-code\\settings.json';
|
|
62
|
+
}
|
|
63
|
+
return '/etc/llxprt-code/settings.json';
|
|
64
|
+
}
|
|
65
|
+
static getSystemPoliciesDir() {
|
|
66
|
+
return path.join(path.dirname(Storage.getSystemSettingsPath()), 'policies');
|
|
67
|
+
}
|
|
68
|
+
static getGlobalTempDir() {
|
|
69
|
+
return path.join(Storage.getGlobalLlxprtDir(), TMP_DIR_NAME);
|
|
70
|
+
}
|
|
71
|
+
getLlxprtDir() {
|
|
72
|
+
return path.join(this.targetDir, LLXPRT_DIR);
|
|
73
|
+
}
|
|
74
|
+
getProjectTempDir() {
|
|
75
|
+
const hash = this.getFilePathHash(this.getProjectRoot());
|
|
76
|
+
const tempDir = Storage.getGlobalTempDir();
|
|
77
|
+
return path.join(tempDir, hash);
|
|
78
|
+
}
|
|
79
|
+
ensureProjectTempDirExists() {
|
|
80
|
+
fs.mkdirSync(this.getProjectTempDir(), { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
static getOAuthCredsPath() {
|
|
83
|
+
return path.join(Storage.getGlobalLlxprtDir(), OAUTH_FILE);
|
|
84
|
+
}
|
|
85
|
+
getProjectRoot() {
|
|
86
|
+
return this.targetDir;
|
|
87
|
+
}
|
|
88
|
+
getFilePathHash(filePath) {
|
|
89
|
+
return crypto.createHash('sha256').update(filePath).digest('hex');
|
|
90
|
+
}
|
|
91
|
+
getHistoryDir() {
|
|
92
|
+
const hash = this.getFilePathHash(this.getProjectRoot());
|
|
93
|
+
const historyDir = path.join(Storage.getGlobalLlxprtDir(), 'history');
|
|
94
|
+
return path.join(historyDir, hash);
|
|
95
|
+
}
|
|
96
|
+
getWorkspaceSettingsPath() {
|
|
97
|
+
return path.join(this.getLlxprtDir(), 'settings.json');
|
|
98
|
+
}
|
|
99
|
+
getProjectCommandsDir() {
|
|
100
|
+
return path.join(this.getLlxprtDir(), 'commands');
|
|
101
|
+
}
|
|
102
|
+
getProjectSkillsDir() {
|
|
103
|
+
return path.join(this.getLlxprtDir(), 'skills');
|
|
104
|
+
}
|
|
105
|
+
getProjectTempCheckpointsDir() {
|
|
106
|
+
return path.join(this.getProjectTempDir(), 'checkpoints');
|
|
107
|
+
}
|
|
108
|
+
getExtensionsDir() {
|
|
109
|
+
return path.join(this.getLlxprtDir(), 'extensions');
|
|
110
|
+
}
|
|
111
|
+
getExtensionsConfigPath() {
|
|
112
|
+
return path.join(this.getExtensionsDir(), 'llxprt-extension.json');
|
|
113
|
+
}
|
|
114
|
+
getHistoryFilePath() {
|
|
115
|
+
return path.join(this.getProjectTempDir(), 'shell_history');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/config/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Vybestack LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { StorageLogger } from '../types/logger.js';
|
|
7
|
+
export declare class ConversationFileWriter {
|
|
8
|
+
private logPath;
|
|
9
|
+
private currentLogFile;
|
|
10
|
+
private logger;
|
|
11
|
+
constructor(logPath?: string, logger?: StorageLogger);
|
|
12
|
+
writeEntry(entry: Record<string, unknown>): void;
|
|
13
|
+
writeRequest(provider: string, messages: unknown[], context?: Record<string, unknown>): void;
|
|
14
|
+
writeResponse(provider: string, response: unknown, metadata?: Record<string, unknown>): void;
|
|
15
|
+
writeToolCall(provider: string, toolName: string, context?: Record<string, unknown>): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Returns the process-wide ConversationFileWriter singleton.
|
|
19
|
+
*
|
|
20
|
+
* First-call-wins: the `logPath` provided on the first invocation determines
|
|
21
|
+
* the writer's output directory for the lifetime of the process. Subsequent
|
|
22
|
+
* calls return the same instance and IGNORE any `logPath` argument. To target
|
|
23
|
+
* a different path (e.g. in tests), call
|
|
24
|
+
* {@link resetConversationFileWriterForTesting} first.
|
|
25
|
+
*/
|
|
26
|
+
export declare function getConversationFileWriter(logPath?: string): ConversationFileWriter;
|
|
27
|
+
export declare function resetConversationFileWriterForTesting(): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Vybestack LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as os from 'os';
|
|
9
|
+
import { NullStorageLoggerImpl } from '../types/logger.js';
|
|
10
|
+
export class ConversationFileWriter {
|
|
11
|
+
logPath;
|
|
12
|
+
currentLogFile;
|
|
13
|
+
logger;
|
|
14
|
+
constructor(logPath, logger) {
|
|
15
|
+
this.logPath =
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional falsy coalescing: empty logPath string should fall through to default path
|
|
17
|
+
logPath || path.join(os.homedir(), '.llxprt', 'conversations');
|
|
18
|
+
this.currentLogFile = path.join(this.logPath, `conversation-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
19
|
+
this.logger = logger ?? new NullStorageLoggerImpl();
|
|
20
|
+
}
|
|
21
|
+
writeEntry(entry) {
|
|
22
|
+
try {
|
|
23
|
+
const logEntry = {
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
...entry,
|
|
26
|
+
};
|
|
27
|
+
const line = JSON.stringify(logEntry) + '\n';
|
|
28
|
+
fs.mkdirSync(this.logPath, { recursive: true });
|
|
29
|
+
fs.appendFileSync(this.currentLogFile, line);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
this.logger.error('Failed to write log entry:', error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
writeRequest(provider, messages, context) {
|
|
36
|
+
this.writeEntry({
|
|
37
|
+
type: 'request',
|
|
38
|
+
provider,
|
|
39
|
+
messages,
|
|
40
|
+
context,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
writeResponse(provider, response, metadata) {
|
|
44
|
+
this.writeEntry({
|
|
45
|
+
type: 'response',
|
|
46
|
+
provider,
|
|
47
|
+
response,
|
|
48
|
+
metadata,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
writeToolCall(provider, toolName, context) {
|
|
52
|
+
this.writeEntry({
|
|
53
|
+
type: 'tool_call',
|
|
54
|
+
provider,
|
|
55
|
+
tool: toolName,
|
|
56
|
+
...context,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Singleton instance
|
|
61
|
+
let fileWriter = null;
|
|
62
|
+
/**
|
|
63
|
+
* Returns the process-wide ConversationFileWriter singleton.
|
|
64
|
+
*
|
|
65
|
+
* First-call-wins: the `logPath` provided on the first invocation determines
|
|
66
|
+
* the writer's output directory for the lifetime of the process. Subsequent
|
|
67
|
+
* calls return the same instance and IGNORE any `logPath` argument. To target
|
|
68
|
+
* a different path (e.g. in tests), call
|
|
69
|
+
* {@link resetConversationFileWriterForTesting} first.
|
|
70
|
+
*/
|
|
71
|
+
export function getConversationFileWriter(logPath) {
|
|
72
|
+
fileWriter ??= new ConversationFileWriter(logPath);
|
|
73
|
+
return fileWriter;
|
|
74
|
+
}
|
|
75
|
+
export function resetConversationFileWriterForTesting() {
|
|
76
|
+
fileWriter = null;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=ConversationFileWriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConversationFileWriter.js","sourceRoot":"","sources":["../../../src/conversation/ConversationFileWriter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,OAAO,sBAAsB;IACzB,OAAO,CAAS;IAChB,cAAc,CAAS;IACvB,MAAM,CAAgB;IAE9B,YAAY,OAAgB,EAAE,MAAsB;QAClD,IAAI,CAAC,OAAO;YACV,kKAAkK;YAClK,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;QACjE,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,CAC7B,IAAI,CAAC,OAAO,EACZ,gBAAgB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAC/D,CAAC;QACF,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,IAAI,qBAAqB,EAAE,CAAC;IACtD,CAAC;IAED,UAAU,CAAC,KAA8B;QACvC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG;gBACf,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBACnC,GAAG,KAAK;aACT,CAAC;YACF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;YAC7C,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChD,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,YAAY,CACV,QAAgB,EAChB,QAAmB,EACnB,OAAiC;QAEjC,IAAI,CAAC,UAAU,CAAC;YACd,IAAI,EAAE,SAAS;YACf,QAAQ;YACR,QAAQ;YACR,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IAED,aAAa,CACX,QAAgB,EAChB,QAAiB,EACjB,QAAkC;QAElC,IAAI,CAAC,UAAU,CAAC;YACd,IAAI,EAAE,UAAU;YAChB,QAAQ;YACR,QAAQ;YACR,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;IAED,aAAa,CACX,QAAgB,EAChB,QAAgB,EAChB,OAAiC;QAEjC,IAAI,CAAC,UAAU,CAAC;YACd,IAAI,EAAE,WAAW;YACjB,QAAQ;YACR,IAAI,EAAE,QAAQ;YACd,GAAG,OAAO;SACX,CAAC,CAAC;IACL,CAAC;CACF;AAED,qBAAqB;AACrB,IAAI,UAAU,GAAkC,IAAI,CAAC;AAErD;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAgB;IAEhB,UAAU,KAAK,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,qCAAqC;IACnD,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type { StorageLogger, NullStorageLogger } from './types/logger.js';
|
|
2
|
+
export { NullStorageLoggerImpl } from './types/logger.js';
|
|
3
|
+
export { Storage, LLXPRT_DIR, PROVIDER_ACCOUNTS_FILENAME, OAUTH_FILE, } from './config/storage.js';
|
|
4
|
+
export { FileSystemService, StandardFileSystemService, } from './services/fileSystemService.js';
|
|
5
|
+
export { FileDiscoveryService } from './services/fileDiscoveryService.js';
|
|
6
|
+
export type { FilterFilesOptions, FilterReport, } from './services/fileDiscoveryService.js';
|
|
7
|
+
export { SecureStore, SecureStoreError, createDefaultKeyringAdapter, } from './secure-store/secure-store.js';
|
|
8
|
+
export type { KeyringAdapter, SecureStoreErrorCode, SecureStoreOptions, } from './secure-store/secure-store.js';
|
|
9
|
+
export { ProviderKeyStorage, KEY_NAME_REGEX, getProviderKeyStorage, resetProviderKeyStorage, validateKeyName, } from './secure-store/provider-key-storage.js';
|
|
10
|
+
export { SESSION_FILE_PREFIX } from './session/sessionTypes.js';
|
|
11
|
+
export type { ConversationRecord, BaseMessageRecord, ToolCallRecord, } from './session/sessionTypes.js';
|
|
12
|
+
export { ConversationFileWriter, getConversationFileWriter, } from './conversation/ConversationFileWriter.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { NullStorageLoggerImpl } from './types/logger.js';
|
|
2
|
+
// Storage paths and constants
|
|
3
|
+
export { Storage, LLXPRT_DIR, PROVIDER_ACCOUNTS_FILENAME, OAUTH_FILE, } from './config/storage.js';
|
|
4
|
+
// File services
|
|
5
|
+
export { FileSystemService, StandardFileSystemService, } from './services/fileSystemService.js';
|
|
6
|
+
export { FileDiscoveryService } from './services/fileDiscoveryService.js';
|
|
7
|
+
// Secure storage
|
|
8
|
+
export { SecureStore, SecureStoreError, createDefaultKeyringAdapter, } from './secure-store/secure-store.js';
|
|
9
|
+
export { ProviderKeyStorage, KEY_NAME_REGEX, getProviderKeyStorage, resetProviderKeyStorage, validateKeyName, } from './secure-store/provider-key-storage.js';
|
|
10
|
+
// Session types and constants
|
|
11
|
+
export { SESSION_FILE_PREFIX } from './session/sessionTypes.js';
|
|
12
|
+
// Conversation file writer
|
|
13
|
+
export { ConversationFileWriter, getConversationFileWriter, } from './conversation/ConversationFileWriter.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,8BAA8B;AAC9B,OAAO,EACL,OAAO,EACP,UAAU,EACV,0BAA0B,EAC1B,UAAU,GACX,MAAM,qBAAqB,CAAC;AAE7B,gBAAgB;AAChB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAM1E,iBAAiB;AACjB,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,2BAA2B,GAC5B,MAAM,gCAAgC,CAAC;AAMxC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,eAAe,GAChB,MAAM,wCAAwC,CAAC;AAEhD,8BAA8B;AAC9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAOhE,2BAA2B;AAC3B,OAAO,EACL,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,0CAA0C,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Vybestack LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { SecureStore } from './secure-store.js';
|
|
7
|
+
/** @pseudocode line 1 */
|
|
8
|
+
export declare const KEY_NAME_REGEX: RegExp;
|
|
9
|
+
/**
|
|
10
|
+
* Validates a key name against the allowed pattern.
|
|
11
|
+
* @throws {Error} if the name does not match KEY_NAME_REGEX
|
|
12
|
+
*
|
|
13
|
+
* @plan PLAN-20260211-SECURESTORE.P12
|
|
14
|
+
* @pseudocode lines 3-9
|
|
15
|
+
* @requirement R10.1, R10.2
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateKeyName(name: string): void;
|
|
18
|
+
/**
|
|
19
|
+
* @plan PLAN-20260211-SECURESTORE.P12
|
|
20
|
+
* @pseudocode lines 11-65
|
|
21
|
+
* @requirement R9.1
|
|
22
|
+
*/
|
|
23
|
+
export declare class ProviderKeyStorage {
|
|
24
|
+
private readonly secureStore;
|
|
25
|
+
/** @pseudocode lines 16-24 */
|
|
26
|
+
constructor(options?: {
|
|
27
|
+
secureStore?: SecureStore;
|
|
28
|
+
});
|
|
29
|
+
/** @pseudocode lines 26-39 */
|
|
30
|
+
saveKey(name: string, apiKey: string): Promise<void>;
|
|
31
|
+
/** @pseudocode lines 41-46 */
|
|
32
|
+
getKey(name: string): Promise<string | null>;
|
|
33
|
+
/** @pseudocode lines 48-53 */
|
|
34
|
+
deleteKey(name: string): Promise<boolean>;
|
|
35
|
+
/** @pseudocode lines 55-57 */
|
|
36
|
+
listKeys(): Promise<string[]>;
|
|
37
|
+
/** @pseudocode lines 59-64 */
|
|
38
|
+
hasKey(name: string): Promise<boolean>;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns the singleton ProviderKeyStorage instance for direct host access.
|
|
42
|
+
*
|
|
43
|
+
* @internal **DO NOT call directly in consumer code.**
|
|
44
|
+
* Use `createProviderKeyStorage()` from `credential-store-factory.ts` instead.
|
|
45
|
+
* This ensures proper environment detection (sandbox vs. direct mode)
|
|
46
|
+
* and consistent behavior across the application.
|
|
47
|
+
*
|
|
48
|
+
* @pseudocode lines 70-74
|
|
49
|
+
* @plan PLAN-20250214-CREDPROXY.P36
|
|
50
|
+
*/
|
|
51
|
+
export declare function getProviderKeyStorage(): ProviderKeyStorage;
|
|
52
|
+
/** @pseudocode lines 77-79 */
|
|
53
|
+
export declare function resetProviderKeyStorage(): void;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Vybestack LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Named API key management backed by SecureStore.
|
|
8
|
+
*
|
|
9
|
+
* Provides CRUD operations for named provider API keys with validation,
|
|
10
|
+
* trimming, and singleton access. All storage is delegated to SecureStore.
|
|
11
|
+
*
|
|
12
|
+
* @plan PLAN-20260211-SECURESTORE.P12
|
|
13
|
+
* @requirement R9.1, R10.1
|
|
14
|
+
*/
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import * as os from 'node:os';
|
|
17
|
+
import { SecureStore } from './secure-store.js';
|
|
18
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
19
|
+
/** @pseudocode line 1 */
|
|
20
|
+
export const KEY_NAME_REGEX = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
21
|
+
/** @pseudocode line 13 */
|
|
22
|
+
const SERVICE_NAME = 'llxprt-code-provider-keys';
|
|
23
|
+
/** @pseudocode line 14 */
|
|
24
|
+
const DEFAULT_FALLBACK_DIR = () => {
|
|
25
|
+
const homeDir = os.homedir();
|
|
26
|
+
if (typeof homeDir === 'string' && homeDir.length > 0) {
|
|
27
|
+
return path.join(homeDir, '.llxprt', 'provider-keys');
|
|
28
|
+
}
|
|
29
|
+
const tmpDir = os.tmpdir();
|
|
30
|
+
return path.join(tmpDir, 'llxprt-provider-keys');
|
|
31
|
+
};
|
|
32
|
+
// ─── Validation ──────────────────────────────────────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* Validates a key name against the allowed pattern.
|
|
35
|
+
* @throws {Error} if the name does not match KEY_NAME_REGEX
|
|
36
|
+
*
|
|
37
|
+
* @plan PLAN-20260211-SECURESTORE.P12
|
|
38
|
+
* @pseudocode lines 3-9
|
|
39
|
+
* @requirement R10.1, R10.2
|
|
40
|
+
*/
|
|
41
|
+
export function validateKeyName(name) {
|
|
42
|
+
if (!KEY_NAME_REGEX.test(name)) {
|
|
43
|
+
throw new Error(`Key name '${name}' is invalid. Use only letters, numbers, dashes, underscores, and dots (1-64 chars).`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// ─── ProviderKeyStorage Class ────────────────────────────────────────────────
|
|
47
|
+
/**
|
|
48
|
+
* @plan PLAN-20260211-SECURESTORE.P12
|
|
49
|
+
* @pseudocode lines 11-65
|
|
50
|
+
* @requirement R9.1
|
|
51
|
+
*/
|
|
52
|
+
export class ProviderKeyStorage {
|
|
53
|
+
secureStore;
|
|
54
|
+
/** @pseudocode lines 16-24 */
|
|
55
|
+
constructor(options) {
|
|
56
|
+
this.secureStore =
|
|
57
|
+
options?.secureStore ??
|
|
58
|
+
new SecureStore(SERVICE_NAME, {
|
|
59
|
+
fallbackDir: DEFAULT_FALLBACK_DIR(),
|
|
60
|
+
fallbackPolicy: 'allow',
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** @pseudocode lines 26-39 */
|
|
64
|
+
async saveKey(name, apiKey) {
|
|
65
|
+
validateKeyName(name);
|
|
66
|
+
let trimmed = apiKey.trim();
|
|
67
|
+
while (trimmed.endsWith('\n') || trimmed.endsWith('\r')) {
|
|
68
|
+
trimmed = trimmed.slice(0, -1);
|
|
69
|
+
}
|
|
70
|
+
if (trimmed.length === 0) {
|
|
71
|
+
throw new Error('API key value cannot be empty.');
|
|
72
|
+
}
|
|
73
|
+
await this.secureStore.set(name, trimmed);
|
|
74
|
+
}
|
|
75
|
+
/** @pseudocode lines 41-46 */
|
|
76
|
+
async getKey(name) {
|
|
77
|
+
validateKeyName(name);
|
|
78
|
+
return this.secureStore.get(name);
|
|
79
|
+
}
|
|
80
|
+
/** @pseudocode lines 48-53 */
|
|
81
|
+
async deleteKey(name) {
|
|
82
|
+
validateKeyName(name);
|
|
83
|
+
return this.secureStore.delete(name);
|
|
84
|
+
}
|
|
85
|
+
/** @pseudocode lines 55-57 */
|
|
86
|
+
async listKeys() {
|
|
87
|
+
return this.secureStore.list();
|
|
88
|
+
}
|
|
89
|
+
/** @pseudocode lines 59-64 */
|
|
90
|
+
async hasKey(name) {
|
|
91
|
+
validateKeyName(name);
|
|
92
|
+
return this.secureStore.has(name);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// ─── Singleton ───────────────────────────────────────────────────────────────
|
|
96
|
+
/** @pseudocode line 68 */
|
|
97
|
+
let providerKeyStorageInstance = null;
|
|
98
|
+
/**
|
|
99
|
+
* Returns the singleton ProviderKeyStorage instance for direct host access.
|
|
100
|
+
*
|
|
101
|
+
* @internal **DO NOT call directly in consumer code.**
|
|
102
|
+
* Use `createProviderKeyStorage()` from `credential-store-factory.ts` instead.
|
|
103
|
+
* This ensures proper environment detection (sandbox vs. direct mode)
|
|
104
|
+
* and consistent behavior across the application.
|
|
105
|
+
*
|
|
106
|
+
* @pseudocode lines 70-74
|
|
107
|
+
* @plan PLAN-20250214-CREDPROXY.P36
|
|
108
|
+
*/
|
|
109
|
+
export function getProviderKeyStorage() {
|
|
110
|
+
providerKeyStorageInstance ??= new ProviderKeyStorage();
|
|
111
|
+
return providerKeyStorageInstance;
|
|
112
|
+
}
|
|
113
|
+
/** @pseudocode lines 77-79 */
|
|
114
|
+
export function resetProviderKeyStorage() {
|
|
115
|
+
providerKeyStorageInstance = null;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=provider-key-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-key-storage.js","sourceRoot":"","sources":["../../../src/secure-store/provider-key-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Vybestack LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import type { StorageLogger } from '../types/logger.js';
|
|
7
|
+
export type SecureStoreErrorCode = 'UNAVAILABLE' | 'LOCKED' | 'DENIED' | 'CORRUPT' | 'TIMEOUT' | 'NOT_FOUND';
|
|
8
|
+
export declare class SecureStoreError extends Error {
|
|
9
|
+
readonly code: SecureStoreErrorCode;
|
|
10
|
+
readonly remediation: string;
|
|
11
|
+
constructor(message: string, code: SecureStoreErrorCode, remediation: string);
|
|
12
|
+
}
|
|
13
|
+
export interface KeyringAdapter {
|
|
14
|
+
getPassword(service: string, account: string): Promise<string | null>;
|
|
15
|
+
setPassword(service: string, account: string, password: string): Promise<void>;
|
|
16
|
+
deletePassword(service: string, account: string): Promise<boolean>;
|
|
17
|
+
findCredentials?(service: string): Promise<Array<{
|
|
18
|
+
account: string;
|
|
19
|
+
password: string;
|
|
20
|
+
}>>;
|
|
21
|
+
}
|
|
22
|
+
export interface SecureStoreOptions {
|
|
23
|
+
fallbackDir?: string;
|
|
24
|
+
fallbackPolicy?: 'allow' | 'deny';
|
|
25
|
+
keyringLoader?: () => Promise<KeyringAdapter | null>;
|
|
26
|
+
logger?: StorageLogger;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Creates a default KeyringAdapter by loading @napi-rs/keyring.
|
|
30
|
+
* Exported so that other modules can reuse this without duplicating
|
|
31
|
+
* the @napi-rs/keyring import.
|
|
32
|
+
*
|
|
33
|
+
* @plan PLAN-20260211-SECURESTORE.P08
|
|
34
|
+
*/
|
|
35
|
+
export declare function createDefaultKeyringAdapter(): Promise<KeyringAdapter | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Stores and retrieves secrets via the OS keychain or encrypted file fallback.
|
|
38
|
+
*
|
|
39
|
+
* @plan PLAN-20260211-SECURESTORE.P06
|
|
40
|
+
* @requirement R1.1, R1.3
|
|
41
|
+
*/
|
|
42
|
+
export declare class SecureStore {
|
|
43
|
+
private readonly serviceName;
|
|
44
|
+
private readonly fallbackPolicy;
|
|
45
|
+
private readonly keyringLoaderFn;
|
|
46
|
+
private readonly fallbackDir;
|
|
47
|
+
private readonly logger;
|
|
48
|
+
private keyringInstance;
|
|
49
|
+
private keyringLoadAttempted;
|
|
50
|
+
private probeCache;
|
|
51
|
+
private readonly PROBE_TTL_MS;
|
|
52
|
+
private consecutiveKeyringFailures;
|
|
53
|
+
private readonly KEYRING_FAILURE_THRESHOLD;
|
|
54
|
+
constructor(serviceName: string, options?: SecureStoreOptions);
|
|
55
|
+
private getKeyring;
|
|
56
|
+
private validateKey;
|
|
57
|
+
private getFallbackFilePath;
|
|
58
|
+
private recordKeyringSuccess;
|
|
59
|
+
private recordKeyringFailure;
|
|
60
|
+
isKeychainAvailable(): Promise<boolean>;
|
|
61
|
+
private writeFallbackAfterKeyringSuccess;
|
|
62
|
+
set(key: string, value: string): Promise<void>;
|
|
63
|
+
get(key: string): Promise<string | null>;
|
|
64
|
+
delete(key: string): Promise<boolean>;
|
|
65
|
+
list(): Promise<string[]>;
|
|
66
|
+
has(key: string): Promise<boolean>;
|
|
67
|
+
private writeFallbackFile;
|
|
68
|
+
private readFallbackFile;
|
|
69
|
+
}
|