@dmsdc-ai/aigentry-brain 0.0.1

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 (136) hide show
  1. package/bin/aigentry-brain-mcp.mjs +17 -0
  2. package/bin/aigentry-brain-setup.mjs +17 -0
  3. package/bin/aigentry-brain.mjs +17 -0
  4. package/dist/audit/AuditTrail.d.ts +15 -0
  5. package/dist/audit/AuditTrail.js +43 -0
  6. package/dist/audit/AuditTrail.js.map +1 -0
  7. package/dist/backend/GitBackend.d.ts +27 -0
  8. package/dist/backend/GitBackend.js +201 -0
  9. package/dist/backend/GitBackend.js.map +1 -0
  10. package/dist/backend/SyncBackend.d.ts +13 -0
  11. package/dist/backend/SyncBackend.js +2 -0
  12. package/dist/backend/SyncBackend.js.map +1 -0
  13. package/dist/cli/AutoUpdater.d.ts +7 -0
  14. package/dist/cli/AutoUpdater.js +275 -0
  15. package/dist/cli/AutoUpdater.js.map +1 -0
  16. package/dist/cli/ConfigStore.d.ts +17 -0
  17. package/dist/cli/ConfigStore.js +50 -0
  18. package/dist/cli/ConfigStore.js.map +1 -0
  19. package/dist/cli/GhIntegration.d.ts +55 -0
  20. package/dist/cli/GhIntegration.js +192 -0
  21. package/dist/cli/GhIntegration.js.map +1 -0
  22. package/dist/cli/Prerequisites.d.ts +48 -0
  23. package/dist/cli/Prerequisites.js +182 -0
  24. package/dist/cli/Prerequisites.js.map +1 -0
  25. package/dist/cli/SetupWizard.d.ts +26 -0
  26. package/dist/cli/SetupWizard.js +407 -0
  27. package/dist/cli/SetupWizard.js.map +1 -0
  28. package/dist/cli/braincli.d.ts +2 -0
  29. package/dist/cli/braincli.js +260 -0
  30. package/dist/cli/braincli.js.map +1 -0
  31. package/dist/cli/setup.d.ts +25 -0
  32. package/dist/cli/setup.js +238 -0
  33. package/dist/cli/setup.js.map +1 -0
  34. package/dist/context/ConfidenceGuard.d.ts +11 -0
  35. package/dist/context/ConfidenceGuard.js +32 -0
  36. package/dist/context/ConfidenceGuard.js.map +1 -0
  37. package/dist/context/ContextBudgetPolicy.d.ts +21 -0
  38. package/dist/context/ContextBudgetPolicy.js +136 -0
  39. package/dist/context/ContextBudgetPolicy.js.map +1 -0
  40. package/dist/context/ContextPacker.d.ts +30 -0
  41. package/dist/context/ContextPacker.js +219 -0
  42. package/dist/context/ContextPacker.js.map +1 -0
  43. package/dist/context/ContextRestoreService.d.ts +39 -0
  44. package/dist/context/ContextRestoreService.js +134 -0
  45. package/dist/context/ContextRestoreService.js.map +1 -0
  46. package/dist/contract/BrainContract.d.ts +93 -0
  47. package/dist/contract/BrainContract.js +245 -0
  48. package/dist/contract/BrainContract.js.map +1 -0
  49. package/dist/core/ContentDedup.d.ts +43 -0
  50. package/dist/core/ContentDedup.js +145 -0
  51. package/dist/core/ContentDedup.js.map +1 -0
  52. package/dist/core/EntityGraph.d.ts +66 -0
  53. package/dist/core/EntityGraph.js +196 -0
  54. package/dist/core/EntityGraph.js.map +1 -0
  55. package/dist/core/EntrySchema.d.ts +46 -0
  56. package/dist/core/EntrySchema.js +4 -0
  57. package/dist/core/EntrySchema.js.map +1 -0
  58. package/dist/core/GraphStore.d.ts +16 -0
  59. package/dist/core/GraphStore.js +29 -0
  60. package/dist/core/GraphStore.js.map +1 -0
  61. package/dist/core/MemoryDecay.d.ts +49 -0
  62. package/dist/core/MemoryDecay.js +113 -0
  63. package/dist/core/MemoryDecay.js.map +1 -0
  64. package/dist/core/ProfileFormat.d.ts +38 -0
  65. package/dist/core/ProfileFormat.js +254 -0
  66. package/dist/core/ProfileFormat.js.map +1 -0
  67. package/dist/core/ProfileManager.d.ts +80 -0
  68. package/dist/core/ProfileManager.js +269 -0
  69. package/dist/core/ProfileManager.js.map +1 -0
  70. package/dist/core/SchemaMigration.d.ts +12 -0
  71. package/dist/core/SchemaMigration.js +34 -0
  72. package/dist/core/SchemaMigration.js.map +1 -0
  73. package/dist/crypto/AgeCrypto.d.ts +26 -0
  74. package/dist/crypto/AgeCrypto.js +101 -0
  75. package/dist/crypto/AgeCrypto.js.map +1 -0
  76. package/dist/index.d.ts +38 -0
  77. package/dist/index.js +30 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/mcp/BrainMcpServer.d.ts +13 -0
  80. package/dist/mcp/BrainMcpServer.js +223 -0
  81. package/dist/mcp/BrainMcpServer.js.map +1 -0
  82. package/dist/mcp/cli.d.ts +2 -0
  83. package/dist/mcp/cli.js +107 -0
  84. package/dist/mcp/cli.js.map +1 -0
  85. package/dist/metrics/ResumeMetrics.d.ts +20 -0
  86. package/dist/metrics/ResumeMetrics.js +46 -0
  87. package/dist/metrics/ResumeMetrics.js.map +1 -0
  88. package/dist/peers/PeerStore.d.ts +17 -0
  89. package/dist/peers/PeerStore.js +65 -0
  90. package/dist/peers/PeerStore.js.map +1 -0
  91. package/dist/policy/PolicyEngine.d.ts +16 -0
  92. package/dist/policy/PolicyEngine.js +70 -0
  93. package/dist/policy/PolicyEngine.js.map +1 -0
  94. package/dist/policy/PolicyEnvelope.d.ts +7 -0
  95. package/dist/policy/PolicyEnvelope.js +2 -0
  96. package/dist/policy/PolicyEnvelope.js.map +1 -0
  97. package/dist/policy/RetentionParser.d.ts +6 -0
  98. package/dist/policy/RetentionParser.js +48 -0
  99. package/dist/policy/RetentionParser.js.map +1 -0
  100. package/dist/shared/AtomicWrite.d.ts +1 -0
  101. package/dist/shared/AtomicWrite.js +11 -0
  102. package/dist/shared/AtomicWrite.js.map +1 -0
  103. package/dist/shared/Clock.d.ts +11 -0
  104. package/dist/shared/Clock.js +17 -0
  105. package/dist/shared/Clock.js.map +1 -0
  106. package/dist/shared/Config.d.ts +15 -0
  107. package/dist/shared/Config.js +67 -0
  108. package/dist/shared/Config.js.map +1 -0
  109. package/dist/shared/Encryption.d.ts +19 -0
  110. package/dist/shared/Encryption.js +47 -0
  111. package/dist/shared/Encryption.js.map +1 -0
  112. package/dist/shared/Logger.d.ts +12 -0
  113. package/dist/shared/Logger.js +40 -0
  114. package/dist/shared/Logger.js.map +1 -0
  115. package/dist/shared/Mutex.d.ts +7 -0
  116. package/dist/shared/Mutex.js +34 -0
  117. package/dist/shared/Mutex.js.map +1 -0
  118. package/dist/shared/SetupErrors.d.ts +31 -0
  119. package/dist/shared/SetupErrors.js +155 -0
  120. package/dist/shared/SetupErrors.js.map +1 -0
  121. package/dist/status/SyncStatusStore.d.ts +17 -0
  122. package/dist/status/SyncStatusStore.js +48 -0
  123. package/dist/status/SyncStatusStore.js.map +1 -0
  124. package/dist/sync/AutoCommitter.d.ts +17 -0
  125. package/dist/sync/AutoCommitter.js +68 -0
  126. package/dist/sync/AutoCommitter.js.map +1 -0
  127. package/dist/sync/ConflictResolver.d.ts +7 -0
  128. package/dist/sync/ConflictResolver.js +56 -0
  129. package/dist/sync/ConflictResolver.js.map +1 -0
  130. package/dist/sync/PushPullManager.d.ts +23 -0
  131. package/dist/sync/PushPullManager.js +155 -0
  132. package/dist/sync/PushPullManager.js.map +1 -0
  133. package/dist/sync/SyncEngine.d.ts +43 -0
  134. package/dist/sync/SyncEngine.js +145 -0
  135. package/dist/sync/SyncEngine.js.map +1 -0
  136. package/package.json +65 -0
@@ -0,0 +1,20 @@
1
+ import type { Entry } from '../core/EntrySchema.js';
2
+ export interface ResumeResult {
3
+ resumeMs: number;
4
+ expectedCount: number;
5
+ actualCount: number;
6
+ lossRate: number;
7
+ success: boolean;
8
+ }
9
+ export interface ResumeTimer {
10
+ stop(expectedEntries: Entry[], actualEntries: Entry[]): ResumeResult;
11
+ }
12
+ /**
13
+ * Start a resume timer. Call stop() with expected/actual entries
14
+ * to get the ResumeResult with timing and loss metrics.
15
+ */
16
+ export declare function startResumeTimer(): ResumeTimer;
17
+ /**
18
+ * Compute resume metrics from pre-collected data (no timer).
19
+ */
20
+ export declare function computeResumeResult(resumeMs: number, expectedEntries: Entry[], actualEntries: Entry[]): ResumeResult;
@@ -0,0 +1,46 @@
1
+ /** Compute lossRate from expected vs actual entry IDs. */
2
+ function computeLossRate(expected, actual) {
3
+ if (expected.length === 0)
4
+ return 0;
5
+ const actualIds = new Set(actual.map(e => e.id));
6
+ let matchCount = 0;
7
+ for (const entry of expected) {
8
+ if (actualIds.has(entry.id))
9
+ matchCount++;
10
+ }
11
+ return (expected.length - matchCount) / expected.length;
12
+ }
13
+ /**
14
+ * Start a resume timer. Call stop() with expected/actual entries
15
+ * to get the ResumeResult with timing and loss metrics.
16
+ */
17
+ export function startResumeTimer() {
18
+ const start = performance.now();
19
+ return {
20
+ stop(expectedEntries, actualEntries) {
21
+ const resumeMs = performance.now() - start;
22
+ const lossRate = computeLossRate(expectedEntries, actualEntries);
23
+ return {
24
+ resumeMs,
25
+ expectedCount: expectedEntries.length,
26
+ actualCount: actualEntries.length,
27
+ lossRate,
28
+ success: lossRate < 0.1 && resumeMs < 5000,
29
+ };
30
+ },
31
+ };
32
+ }
33
+ /**
34
+ * Compute resume metrics from pre-collected data (no timer).
35
+ */
36
+ export function computeResumeResult(resumeMs, expectedEntries, actualEntries) {
37
+ const lossRate = computeLossRate(expectedEntries, actualEntries);
38
+ return {
39
+ resumeMs,
40
+ expectedCount: expectedEntries.length,
41
+ actualCount: actualEntries.length,
42
+ lossRate,
43
+ success: lossRate < 0.1 && resumeMs < 5000,
44
+ };
45
+ }
46
+ //# sourceMappingURL=ResumeMetrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResumeMetrics.js","sourceRoot":"","sources":["../../src/metrics/ResumeMetrics.ts"],"names":[],"mappings":"AAcA,0DAA0D;AAC1D,SAAS,eAAe,CAAC,QAAiB,EAAE,MAAe;IACzD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAAE,UAAU,EAAE,CAAC;IAC5C,CAAC;IACD,OAAO,CAAC,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAEhC,OAAO;QACL,IAAI,CAAC,eAAwB,EAAE,aAAsB;YACnD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YAC3C,MAAM,QAAQ,GAAG,eAAe,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;YAEjE,OAAO;gBACL,QAAQ;gBACR,aAAa,EAAE,eAAe,CAAC,MAAM;gBACrC,WAAW,EAAE,aAAa,CAAC,MAAM;gBACjC,QAAQ;gBACR,OAAO,EAAE,QAAQ,GAAG,GAAG,IAAI,QAAQ,GAAG,IAAI;aAC3C,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAgB,EAChB,eAAwB,EACxB,aAAsB;IAEtB,MAAM,QAAQ,GAAG,eAAe,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IAEjE,OAAO;QACL,QAAQ;QACR,aAAa,EAAE,eAAe,CAAC,MAAM;QACrC,WAAW,EAAE,aAAa,CAAC,MAAM;QACjC,QAAQ;QACR,OAAO,EAAE,QAAQ,GAAG,GAAG,IAAI,QAAQ,GAAG,IAAI;KAC3C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface Peer {
2
+ id: string;
3
+ remote_url?: string;
4
+ last_seen: string;
5
+ status: 'active' | 'inactive';
6
+ }
7
+ export interface PeersFile {
8
+ peers: Peer[];
9
+ }
10
+ export declare class PeerStore {
11
+ private filePath;
12
+ constructor(filePath: string);
13
+ list(): Promise<Peer[]>;
14
+ register(peer: Omit<Peer, 'last_seen' | 'status'>): Promise<Peer>;
15
+ remove(peerId: string): Promise<boolean>;
16
+ getFilePath(): string;
17
+ }
@@ -0,0 +1,65 @@
1
+ import yaml from 'js-yaml';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { mkdir } from 'node:fs/promises';
4
+ import { dirname } from 'node:path';
5
+ import { atomicWrite } from '../shared/AtomicWrite.js';
6
+ export class PeerStore {
7
+ filePath;
8
+ constructor(filePath) {
9
+ this.filePath = filePath;
10
+ }
11
+ async list() {
12
+ let content;
13
+ try {
14
+ content = await readFile(this.filePath, 'utf8');
15
+ }
16
+ catch (err) {
17
+ const e = err;
18
+ if (e.code === 'ENOENT') {
19
+ return [];
20
+ }
21
+ throw err;
22
+ }
23
+ const parsed = yaml.load(content);
24
+ if (!parsed || !Array.isArray(parsed.peers)) {
25
+ return [];
26
+ }
27
+ return parsed.peers;
28
+ }
29
+ async register(peer) {
30
+ const peers = await this.list();
31
+ const now = new Date().toISOString();
32
+ const existingIndex = peers.findIndex(p => p.id === peer.id);
33
+ const registered = {
34
+ ...peer,
35
+ last_seen: now,
36
+ status: 'active',
37
+ };
38
+ if (existingIndex >= 0) {
39
+ peers[existingIndex] = registered;
40
+ }
41
+ else {
42
+ peers.push(registered);
43
+ }
44
+ await mkdir(dirname(this.filePath), { recursive: true });
45
+ const fileContent = { peers };
46
+ await atomicWrite(this.filePath, yaml.dump(fileContent));
47
+ return registered;
48
+ }
49
+ async remove(peerId) {
50
+ const peers = await this.list();
51
+ const index = peers.findIndex(p => p.id === peerId);
52
+ if (index < 0) {
53
+ return false;
54
+ }
55
+ peers.splice(index, 1);
56
+ await mkdir(dirname(this.filePath), { recursive: true });
57
+ const fileContent = { peers };
58
+ await atomicWrite(this.filePath, yaml.dump(fileContent));
59
+ return true;
60
+ }
61
+ getFilePath() {
62
+ return this.filePath;
63
+ }
64
+ }
65
+ //# sourceMappingURL=PeerStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PeerStore.js","sourceRoot":"","sources":["../../src/peers/PeerStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Entry } from '../core/EntrySchema.js';
2
+ import type { PolicyEnvelope } from './PolicyEnvelope.js';
3
+ export interface PolicyConfig {
4
+ currentProjectId: string;
5
+ defaultScope: 'user' | 'project' | 'team';
6
+ }
7
+ export declare class PolicyEngine {
8
+ private config;
9
+ constructor(config: PolicyConfig);
10
+ validateWrite(policy?: PolicyEnvelope): void;
11
+ applyDefaults(policy?: PolicyEnvelope): PolicyEnvelope;
12
+ filterRead(entries: Entry[], options?: {
13
+ projectId?: string;
14
+ now?: Date;
15
+ }): Entry[];
16
+ }
@@ -0,0 +1,70 @@
1
+ import { parseRetentionTTL, isExpired } from './RetentionParser.js';
2
+ const VALID_SCOPES = new Set(['user', 'project', 'team']);
3
+ const VALID_SENSITIVITIES = new Set(['public', 'internal', 'confidential', 'restricted']);
4
+ export class PolicyEngine {
5
+ config;
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ validateWrite(policy) {
10
+ if (!policy) {
11
+ return;
12
+ }
13
+ if (policy.scope !== undefined) {
14
+ if (!VALID_SCOPES.has(policy.scope)) {
15
+ throw new Error(`Invalid scope: "${policy.scope}". Must be one of: ${[...VALID_SCOPES].join(', ')}`);
16
+ }
17
+ }
18
+ if (policy.retention_ttl !== undefined) {
19
+ // Will throw if invalid
20
+ parseRetentionTTL(policy.retention_ttl);
21
+ }
22
+ if (policy.sensitivity !== undefined) {
23
+ if (!VALID_SENSITIVITIES.has(policy.sensitivity)) {
24
+ throw new Error(`Invalid sensitivity: "${policy.sensitivity}". Must be one of: ${[...VALID_SENSITIVITIES].join(', ')}`);
25
+ }
26
+ }
27
+ if (policy.allowed_models !== undefined) {
28
+ if (!Array.isArray(policy.allowed_models) ||
29
+ policy.allowed_models.length === 0 ||
30
+ policy.allowed_models.some(m => typeof m !== 'string')) {
31
+ throw new Error('allowed_models must be a non-empty array of strings');
32
+ }
33
+ }
34
+ if ((policy.scope === 'team' || policy.scope === 'project') &&
35
+ !policy.project_id) {
36
+ // Warn only — do not throw
37
+ console.warn(`[PolicyEngine] Warning: scope="${policy.scope}" but no project_id specified. ` +
38
+ `Defaulting to currentProjectId="${this.config.currentProjectId}".`);
39
+ }
40
+ }
41
+ applyDefaults(policy) {
42
+ return {
43
+ project_id: this.config.currentProjectId,
44
+ scope: this.config.defaultScope,
45
+ ...policy,
46
+ };
47
+ }
48
+ filterRead(entries, options) {
49
+ const projectId = options?.projectId ?? this.config.currentProjectId;
50
+ const now = options?.now ?? new Date();
51
+ return entries.filter(entry => {
52
+ // 1. Filter by retention_ttl expiration
53
+ if (entry.policy?.retention_ttl) {
54
+ if (isExpired(entry.policy.retention_ttl, entry.created, now)) {
55
+ return false;
56
+ }
57
+ }
58
+ // 2. Filter by scope + project_id
59
+ if (entry.policy?.scope === 'project' &&
60
+ entry.policy?.project_id &&
61
+ entry.policy.project_id !== projectId) {
62
+ return false;
63
+ }
64
+ // 'user' scope entries are always visible
65
+ // 'team' scope entries are always visible (team access control is Phase 2)
66
+ return true;
67
+ });
68
+ }
69
+ }
70
+ //# sourceMappingURL=PolicyEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicyEngine.js","sourceRoot":"","sources":["../../src/policy/PolicyEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface PolicyEnvelope {
2
+ project_id?: string;
3
+ scope?: 'user' | 'project' | 'team';
4
+ allowed_models?: string[];
5
+ retention_ttl?: string;
6
+ sensitivity?: 'public' | 'internal' | 'confidential' | 'restricted';
7
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=PolicyEnvelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicyEnvelope.js","sourceRoot":"","sources":["../../src/policy/PolicyEnvelope.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ export interface ParsedTTL {
2
+ ms: number;
3
+ forever: boolean;
4
+ }
5
+ export declare function parseRetentionTTL(ttl: string): ParsedTTL;
6
+ export declare function isExpired(ttl: string, createdAt: string, now: Date): boolean;
@@ -0,0 +1,48 @@
1
+ export function parseRetentionTTL(ttl) {
2
+ if (!ttl || ttl.trim() === '') {
3
+ throw new Error('retention_ttl cannot be empty');
4
+ }
5
+ const trimmed = ttl.trim();
6
+ if (trimmed === 'forever') {
7
+ return { ms: Infinity, forever: true };
8
+ }
9
+ const dayMatch = trimmed.match(/^(\d+)d$/);
10
+ if (dayMatch) {
11
+ const days = parseInt(dayMatch[1], 10);
12
+ if (days <= 0) {
13
+ throw new Error(`retention_ttl days must be positive, got: ${ttl}`);
14
+ }
15
+ return { ms: days * 24 * 60 * 60 * 1000, forever: false };
16
+ }
17
+ const hourMatch = trimmed.match(/^(\d+)h$/);
18
+ if (hourMatch) {
19
+ const hours = parseInt(hourMatch[1], 10);
20
+ if (hours <= 0) {
21
+ throw new Error(`retention_ttl hours must be positive, got: ${ttl}`);
22
+ }
23
+ return { ms: hours * 60 * 60 * 1000, forever: false };
24
+ }
25
+ const yearMatch = trimmed.match(/^(\d+)y$/);
26
+ if (yearMatch) {
27
+ const years = parseInt(yearMatch[1], 10);
28
+ if (years <= 0) {
29
+ throw new Error(`retention_ttl years must be positive, got: ${ttl}`);
30
+ }
31
+ return { ms: years * 365 * 24 * 60 * 60 * 1000, forever: false };
32
+ }
33
+ // Handle negative values like "-1d"
34
+ if (trimmed.match(/^-/)) {
35
+ throw new Error(`retention_ttl must be positive, got: ${ttl}`);
36
+ }
37
+ throw new Error(`Invalid retention_ttl format: "${ttl}". Supported formats: "30d", "24h", "1y", "forever"`);
38
+ }
39
+ export function isExpired(ttl, createdAt, now) {
40
+ const parsed = parseRetentionTTL(ttl);
41
+ if (parsed.forever) {
42
+ return false;
43
+ }
44
+ const createdMs = new Date(createdAt).getTime();
45
+ const expiresAt = createdMs + parsed.ms;
46
+ return now.getTime() >= expiresAt;
47
+ }
48
+ //# sourceMappingURL=RetentionParser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RetentionParser.js","sourceRoot":"","sources":["../../src/policy/RetentionParser.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAE3B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvC,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,6CAA6C,GAAG,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5D,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACxD,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,KAAK,GAAG,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACnE,CAAC;IAED,oCAAoC;IACpC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,wCAAwC,GAAG,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,IAAI,KAAK,CACb,kCAAkC,GAAG,qDAAqD,CAC3F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,SAAiB,EAAE,GAAS;IACjE,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAEtC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAChD,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC;IACxC,OAAO,GAAG,CAAC,OAAO,EAAE,IAAI,SAAS,CAAC;AACpC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function atomicWrite(filePath: string, content: string): Promise<void>;
@@ -0,0 +1,11 @@
1
+ import { writeFile, rename, mkdir } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ export async function atomicWrite(filePath, content) {
5
+ const dir = dirname(filePath);
6
+ await mkdir(dir, { recursive: true });
7
+ const tmpPath = join(dir, `.${randomUUID()}.tmp`);
8
+ await writeFile(tmpPath, content, 'utf8');
9
+ await rename(tmpPath, filePath);
10
+ }
11
+ //# sourceMappingURL=AtomicWrite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AtomicWrite.js","sourceRoot":"","sources":["../../src/shared/AtomicWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe;IACjE,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9B,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface Clock {
2
+ now(): Date;
3
+ }
4
+ export declare const SystemClock: Clock;
5
+ export declare class FakeClock implements Clock {
6
+ private _now;
7
+ constructor(now: Date);
8
+ now(): Date;
9
+ advance(ms: number): void;
10
+ set(date: Date): void;
11
+ }
@@ -0,0 +1,17 @@
1
+ export const SystemClock = { now: () => new Date() };
2
+ export class FakeClock {
3
+ _now;
4
+ constructor(now) {
5
+ this._now = new Date(now.getTime());
6
+ }
7
+ now() {
8
+ return new Date(this._now.getTime());
9
+ }
10
+ advance(ms) {
11
+ this._now = new Date(this._now.getTime() + ms);
12
+ }
13
+ set(date) {
14
+ this._now = new Date(date.getTime());
15
+ }
16
+ }
17
+ //# sourceMappingURL=Clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Clock.js","sourceRoot":"","sources":["../../src/shared/Clock.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,WAAW,GAAU,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;AAE5D,MAAM,OAAO,SAAS;IACZ,IAAI,CAAO;IACnB,YAAY,GAAS;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,GAAG;QACD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,CAAC,EAAU;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,GAAG,CAAC,IAAU;QACZ,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ import type { LogLevel } from './Logger.js';
2
+ export interface BrainConfig {
3
+ profilePath: string;
4
+ deviceId: string;
5
+ statusPath: string;
6
+ logLevel: LogLevel;
7
+ serverName: string;
8
+ serverVersion: string;
9
+ remoteUrl?: string;
10
+ repoPath?: string;
11
+ projectId?: string;
12
+ defaultScope?: 'user' | 'project' | 'team';
13
+ peersPath?: string;
14
+ }
15
+ export declare function loadConfig(): BrainConfig;
@@ -0,0 +1,67 @@
1
+ import { homedir, hostname } from 'node:os';
2
+ import { join, dirname } from 'node:path';
3
+ import { readFileSync, existsSync } from 'node:fs';
4
+ import { fileURLToPath } from 'node:url';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ function readPackageVersion() {
8
+ try {
9
+ const pkgPath = join(__dirname, '..', '..', 'package.json');
10
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
11
+ return pkg.version ?? '0.0.0';
12
+ }
13
+ catch {
14
+ return '0.0.0';
15
+ }
16
+ }
17
+ const VALID_LOG_LEVELS = new Set(['debug', 'info', 'warn', 'error']);
18
+ function readConfigJsonSync(configPath) {
19
+ try {
20
+ const raw = readFileSync(configPath, 'utf8');
21
+ return JSON.parse(raw);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ export function loadConfig() {
28
+ // Read config.json as fallback (env vars take priority)
29
+ const configJsonPath = process.env.BRAIN_CONFIG_PATH
30
+ ?? join(homedir(), '.aigentry', 'config.json');
31
+ const configJson = readConfigJsonSync(configJsonPath);
32
+ const logLevelRaw = process.env.BRAIN_LOG_LEVEL ?? 'info';
33
+ if (!VALID_LOG_LEVELS.has(logLevelRaw)) {
34
+ throw new Error(`Invalid BRAIN_LOG_LEVEL: "${logLevelRaw}". Must be one of: debug, info, warn, error.`);
35
+ }
36
+ const remoteUrlRaw = process.env.BRAIN_REMOTE_URL ?? (configJson?.remoteUrl ?? undefined);
37
+ const defaultScopeRaw = process.env.BRAIN_DEFAULT_SCOPE ?? 'user';
38
+ if (defaultScopeRaw !== 'user' && defaultScopeRaw !== 'project' && defaultScopeRaw !== 'team') {
39
+ throw new Error(`Invalid BRAIN_DEFAULT_SCOPE: "${defaultScopeRaw}". Must be one of: user, project, team.`);
40
+ }
41
+ // When sync is enabled and repo is cloned, use repo profile as source of truth
42
+ const repoPath = process.env.BRAIN_REPO_PATH ?? join(homedir(), '.aigentry', 'repo');
43
+ const repoProfilePath = join(repoPath, 'memory-profile.yaml');
44
+ const hasRepo = remoteUrlRaw && existsSync(join(repoPath, '.git'));
45
+ const defaultProfilePath = hasRepo ? repoProfilePath : join(homedir(), '.aigentry', 'profile.yaml');
46
+ const config = {
47
+ profilePath: process.env.BRAIN_PROFILE_PATH ?? defaultProfilePath,
48
+ deviceId: process.env.BRAIN_DEVICE_ID ?? configJson?.deviceId ?? `device-${hostname()}`,
49
+ statusPath: process.env.BRAIN_STATUS_PATH ?? join(homedir(), '.aigentry', 'status.json'),
50
+ logLevel: logLevelRaw,
51
+ serverName: process.env.BRAIN_SERVER_NAME ?? 'aigentry-brain',
52
+ serverVersion: process.env.BRAIN_SERVER_VERSION ?? readPackageVersion(),
53
+ remoteUrl: remoteUrlRaw && remoteUrlRaw !== '' ? remoteUrlRaw : undefined,
54
+ repoPath: process.env.BRAIN_REPO_PATH ?? join(homedir(), '.aigentry', 'repo'),
55
+ projectId: process.env.BRAIN_PROJECT_ID ?? 'default',
56
+ defaultScope: defaultScopeRaw,
57
+ peersPath: process.env.BRAIN_PEERS_PATH ?? join(homedir(), '.aigentry', 'peers.yaml'),
58
+ };
59
+ if (config.profilePath === '') {
60
+ throw new Error('BRAIN_PROFILE_PATH must not be empty');
61
+ }
62
+ if (config.statusPath === '') {
63
+ throw new Error('BRAIN_STATUS_PATH must not be empty');
64
+ }
65
+ return config;
66
+ }
67
+ //# sourceMappingURL=Config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Config.js","sourceRoot":"","sources":["../../src/shared/Config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export declare enum EncryptionMode {
2
+ ACTIVE = "active",
3
+ FALLBACK_PLAINTEXT = "fallback_plaintext",
4
+ DISABLED = "disabled"
5
+ }
6
+ export declare function getEncryptionMode(): EncryptionMode;
7
+ /**
8
+ * Read and decrypt a file.
9
+ * In DISABLED mode: reads plaintext.
10
+ * In ACTIVE mode: tries age decryption, falls back to plaintext on failure.
11
+ * In FALLBACK_PLAINTEXT mode: reads plaintext with warning.
12
+ */
13
+ export declare function readDecrypted(path: string): Promise<string>;
14
+ /**
15
+ * Encrypt a file in-place.
16
+ * No-op: encryption is now handled at the ProfileFormat level using age-encryption npm.
17
+ * Kept for backward compatibility during migration.
18
+ */
19
+ export declare function encryptInPlace(_path: string): Promise<void>;
@@ -0,0 +1,47 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { createLogger } from './Logger.js';
3
+ const logger = createLogger('Encryption');
4
+ export var EncryptionMode;
5
+ (function (EncryptionMode) {
6
+ EncryptionMode["ACTIVE"] = "active";
7
+ EncryptionMode["FALLBACK_PLAINTEXT"] = "fallback_plaintext";
8
+ EncryptionMode["DISABLED"] = "disabled";
9
+ })(EncryptionMode || (EncryptionMode = {}));
10
+ export function getEncryptionMode() {
11
+ const env = process.env.AIGENTRY_ENCRYPTION;
12
+ if (env === 'required' || env === 'active')
13
+ return EncryptionMode.ACTIVE;
14
+ if (env === 'disabled')
15
+ return EncryptionMode.DISABLED;
16
+ // Auto-detect test environment
17
+ if (process.env.VITEST || process.env.NODE_ENV === 'test')
18
+ return EncryptionMode.DISABLED;
19
+ // Default: active (Invisible Security — auto-encrypt, graceful fallback)
20
+ return EncryptionMode.ACTIVE;
21
+ }
22
+ /**
23
+ * Read and decrypt a file.
24
+ * In DISABLED mode: reads plaintext.
25
+ * In ACTIVE mode: tries age decryption, falls back to plaintext on failure.
26
+ * In FALLBACK_PLAINTEXT mode: reads plaintext with warning.
27
+ */
28
+ export async function readDecrypted(path) {
29
+ const mode = getEncryptionMode();
30
+ if (mode === EncryptionMode.DISABLED)
31
+ return readFile(path, 'utf-8');
32
+ // For ACTIVE and FALLBACK: read plaintext (age decryption is handled at ProfileFormat level)
33
+ // This function now only handles raw file reads — encryption/decryption is in ProfileFormat
34
+ return readFile(path, 'utf-8');
35
+ }
36
+ /**
37
+ * Encrypt a file in-place.
38
+ * No-op: encryption is now handled at the ProfileFormat level using age-encryption npm.
39
+ * Kept for backward compatibility during migration.
40
+ */
41
+ export async function encryptInPlace(_path) {
42
+ const mode = getEncryptionMode();
43
+ if (mode === EncryptionMode.DISABLED)
44
+ return;
45
+ // No-op: age-block encryption is done in ProfileFormat.writeToFile()
46
+ }
47
+ //# sourceMappingURL=Encryption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Encryption.js","sourceRoot":"","sources":["../../src/shared/Encryption.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAE1C,MAAM,CAAN,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,mCAAiB,CAAA;IACjB,2DAAyC,CAAA;IACzC,uCAAqB,CAAA;AACvB,CAAC,EAJW,cAAc,KAAd,cAAc,QAIzB;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;IAC5C,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,cAAc,CAAC,MAAM,CAAC;IACzE,IAAI,GAAG,KAAK,UAAU;QAAE,OAAO,cAAc,CAAC,QAAQ,CAAC;IAEvD,+BAA+B;IAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,cAAc,CAAC,QAAQ,CAAC;IAE1F,yEAAyE;IACzE,OAAO,cAAc,CAAC,MAAM,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAY;IAC9C,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,IAAI,IAAI,KAAK,cAAc,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAErE,6FAA6F;IAC7F,4FAA4F;IAC5F,OAAO,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa;IAChD,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,IAAI,IAAI,KAAK,cAAc,CAAC,QAAQ;QAAE,OAAO;IAC7C,qEAAqE;AACvE,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
2
+ export interface Logger {
3
+ debug(msg: string, extra?: Record<string, unknown>): void;
4
+ info(msg: string, extra?: Record<string, unknown>): void;
5
+ warn(msg: string, extra?: Record<string, unknown>): void;
6
+ error(msg: string, extra?: Record<string, unknown>): void;
7
+ }
8
+ export interface LoggerOptions {
9
+ level?: LogLevel;
10
+ deviceId?: string;
11
+ }
12
+ export declare function createLogger(component: string, options?: LoggerOptions): Logger;
@@ -0,0 +1,40 @@
1
+ const LEVEL_ORDER = {
2
+ debug: 0,
3
+ info: 1,
4
+ warn: 2,
5
+ error: 3,
6
+ };
7
+ function resolveLevel(options) {
8
+ if (options?.level)
9
+ return options.level;
10
+ const env = process.env.BRAIN_LOG_LEVEL;
11
+ if (env && env in LEVEL_ORDER)
12
+ return env;
13
+ return 'info';
14
+ }
15
+ export function createLogger(component, options) {
16
+ const minLevel = resolveLevel(options);
17
+ const deviceId = options?.deviceId;
18
+ function write(level, msg, extra) {
19
+ if (LEVEL_ORDER[level] < LEVEL_ORDER[minLevel])
20
+ return;
21
+ const entry = {
22
+ level,
23
+ ts: new Date().toISOString(),
24
+ component,
25
+ msg,
26
+ };
27
+ if (deviceId !== undefined)
28
+ entry['deviceId'] = deviceId;
29
+ if (extra && Object.keys(extra).length > 0)
30
+ entry['extra'] = extra;
31
+ process.stderr.write(JSON.stringify(entry) + '\n');
32
+ }
33
+ return {
34
+ debug: (msg, extra) => write('debug', msg, extra),
35
+ info: (msg, extra) => write('info', msg, extra),
36
+ warn: (msg, extra) => write('warn', msg, extra),
37
+ error: (msg, extra) => write('error', msg, extra),
38
+ };
39
+ }
40
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/shared/Logger.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,GAA6B;IAC5C,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,SAAS,YAAY,CAAC,OAAuB;IAC3C,IAAI,OAAO,EAAE,KAAK;QAAE,OAAO,OAAO,CAAC,KAAK,CAAC;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACxC,IAAI,GAAG,IAAI,GAAG,IAAI,WAAW;QAAE,OAAO,GAAe,CAAC;IACtD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,OAAuB;IACrE,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,CAAC;IAEnC,SAAS,KAAK,CAAC,KAAe,EAAE,GAAW,EAAE,KAA+B;QAC1E,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,WAAW,CAAC,QAAQ,CAAC;YAAE,OAAO;QACvD,MAAM,KAAK,GAA4B;YACrC,KAAK;YACL,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,SAAS;YACT,GAAG;SACJ,CAAC;QACF,IAAI,QAAQ,KAAK,SAAS;YAAE,KAAK,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;QACzD,IAAI,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;QACnE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC;IACrD,CAAC;IAED,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC;QACjD,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC;QAC/C,IAAI,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC;QAC/C,KAAK,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC;KAClD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare class Mutex {
2
+ private _locked;
3
+ private _queue;
4
+ acquire(): Promise<() => void>;
5
+ private release;
6
+ runExclusive<T>(fn: () => Promise<T>): Promise<T>;
7
+ }