opencode-memory-plugin 0.1.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 +73 -0
- package/dist/compression/compressor.d.ts +86 -0
- package/dist/compression/compressor.d.ts.map +1 -0
- package/dist/compression/compressor.js +142 -0
- package/dist/compression/compressor.js.map +1 -0
- package/dist/compression/parser.d.ts +73 -0
- package/dist/compression/parser.d.ts.map +1 -0
- package/dist/compression/parser.js +139 -0
- package/dist/compression/parser.js.map +1 -0
- package/dist/compression/pipeline.d.ts +73 -0
- package/dist/compression/pipeline.d.ts.map +1 -0
- package/dist/compression/pipeline.js +205 -0
- package/dist/compression/pipeline.js.map +1 -0
- package/dist/compression/privacy.d.ts +8 -0
- package/dist/compression/privacy.d.ts.map +1 -0
- package/dist/compression/privacy.js +30 -0
- package/dist/compression/privacy.js.map +1 -0
- package/dist/compression/prompts.d.ts +24 -0
- package/dist/compression/prompts.d.ts.map +1 -0
- package/dist/compression/prompts.js +106 -0
- package/dist/compression/prompts.js.map +1 -0
- package/dist/compression/quality.d.ts +48 -0
- package/dist/compression/quality.d.ts.map +1 -0
- package/dist/compression/quality.js +159 -0
- package/dist/compression/quality.js.map +1 -0
- package/dist/config.d.ts +114 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +265 -0
- package/dist/config.js.map +1 -0
- package/dist/context/generator.d.ts +28 -0
- package/dist/context/generator.d.ts.map +1 -0
- package/dist/context/generator.js +80 -0
- package/dist/context/generator.js.map +1 -0
- package/dist/hooks/chat-message.d.ts +14 -0
- package/dist/hooks/chat-message.d.ts.map +1 -0
- package/dist/hooks/chat-message.js +35 -0
- package/dist/hooks/chat-message.js.map +1 -0
- package/dist/hooks/compaction.d.ts +13 -0
- package/dist/hooks/compaction.d.ts.map +1 -0
- package/dist/hooks/compaction.js +22 -0
- package/dist/hooks/compaction.js.map +1 -0
- package/dist/hooks/events.d.ts +52 -0
- package/dist/hooks/events.d.ts.map +1 -0
- package/dist/hooks/events.js +138 -0
- package/dist/hooks/events.js.map +1 -0
- package/dist/hooks/system-transform.d.ts +14 -0
- package/dist/hooks/system-transform.d.ts.map +1 -0
- package/dist/hooks/system-transform.js +26 -0
- package/dist/hooks/system-transform.js.map +1 -0
- package/dist/hooks/tool-after.d.ts +26 -0
- package/dist/hooks/tool-after.d.ts.map +1 -0
- package/dist/hooks/tool-after.js +88 -0
- package/dist/hooks/tool-after.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +60 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +91 -0
- package/dist/logger.js.map +1 -0
- package/dist/storage/db.d.ts +22 -0
- package/dist/storage/db.d.ts.map +1 -0
- package/dist/storage/db.js +198 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/storage/schema.d.ts +2473 -0
- package/dist/storage/schema.d.ts.map +1 -0
- package/dist/storage/schema.js +100 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/store.d.ts +376 -0
- package/dist/storage/store.d.ts.map +1 -0
- package/dist/storage/store.js +1025 -0
- package/dist/storage/store.js.map +1 -0
- package/dist/tools/memory-forget.d.ts +11 -0
- package/dist/tools/memory-forget.d.ts.map +1 -0
- package/dist/tools/memory-forget.js +249 -0
- package/dist/tools/memory-forget.js.map +1 -0
- package/dist/tools/memory-get.d.ts +10 -0
- package/dist/tools/memory-get.d.ts.map +1 -0
- package/dist/tools/memory-get.js +50 -0
- package/dist/tools/memory-get.js.map +1 -0
- package/dist/tools/memory-search.d.ts +11 -0
- package/dist/tools/memory-search.d.ts.map +1 -0
- package/dist/tools/memory-search.js +38 -0
- package/dist/tools/memory-search.js.map +1 -0
- package/dist/tools/memory-stats.d.ts +39 -0
- package/dist/tools/memory-stats.d.ts.map +1 -0
- package/dist/tools/memory-stats.js +121 -0
- package/dist/tools/memory-stats.js.map +1 -0
- package/dist/tools/memory-timeline.d.ts +10 -0
- package/dist/tools/memory-timeline.d.ts.map +1 -0
- package/dist/tools/memory-timeline.js +49 -0
- package/dist/tools/memory-timeline.js.map +1 -0
- package/dist/types.d.ts +178 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +130 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +308 -0
- package/dist/utils.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Hooks } from "@opencode-ai/plugin";
|
|
2
|
+
import type { Event } from "@opencode-ai/sdk";
|
|
3
|
+
import type { CompressionPipeline } from "../compression/pipeline";
|
|
4
|
+
import type { MemoryLogger } from "../logger";
|
|
5
|
+
import type { PluginConfig, RuntimeState } from "../types";
|
|
6
|
+
/**
|
|
7
|
+
* Creates the event hook that manages session lifecycle and queue recovery.
|
|
8
|
+
*
|
|
9
|
+
* @param pipeline - Compression pipeline.
|
|
10
|
+
* @param config - Plugin configuration.
|
|
11
|
+
* @param state - Runtime state.
|
|
12
|
+
* @param logger - Structured logger.
|
|
13
|
+
* @returns Hook implementation.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createEventHook(pipeline: CompressionPipeline, config: PluginConfig, state: RuntimeState, logger: MemoryLogger): NonNullable<Hooks["event"]>;
|
|
16
|
+
/**
|
|
17
|
+
* Registers a graceful shutdown handler once for the plugin process.
|
|
18
|
+
*
|
|
19
|
+
* @param pipeline - Compression pipeline.
|
|
20
|
+
* @param state - Runtime state.
|
|
21
|
+
* @param logger - Structured logger.
|
|
22
|
+
* @returns Nothing.
|
|
23
|
+
*/
|
|
24
|
+
export declare function registerShutdown(pipeline: CompressionPipeline, state: RuntimeState, logger: MemoryLogger): void;
|
|
25
|
+
/**
|
|
26
|
+
* Schedules summary generation after a debounce interval.
|
|
27
|
+
*
|
|
28
|
+
* @param sessionId - OpenCode session identifier.
|
|
29
|
+
* @param pipeline - Compression pipeline.
|
|
30
|
+
* @param config - Plugin configuration.
|
|
31
|
+
* @param state - Runtime state.
|
|
32
|
+
* @param logger - Structured logger.
|
|
33
|
+
* @returns Nothing.
|
|
34
|
+
*/
|
|
35
|
+
export declare function scheduleSummary(sessionId: string, pipeline: CompressionPipeline, config: PluginConfig, state: RuntimeState, logger: MemoryLogger): void;
|
|
36
|
+
/**
|
|
37
|
+
* Clears a scheduled summary timer.
|
|
38
|
+
*
|
|
39
|
+
* @param sessionId - OpenCode session identifier.
|
|
40
|
+
* @param state - Runtime state.
|
|
41
|
+
* @returns Nothing.
|
|
42
|
+
*/
|
|
43
|
+
export declare function clearSummaryTimer(sessionId: string, state: RuntimeState): void;
|
|
44
|
+
/**
|
|
45
|
+
* Checks whether an event belongs to an internal compressor session.
|
|
46
|
+
*
|
|
47
|
+
* @param event - OpenCode event.
|
|
48
|
+
* @param state - Runtime state.
|
|
49
|
+
* @returns True when the event should be ignored.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isInternalEvent(event: Event, state: RuntimeState): boolean;
|
|
52
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/hooks/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE1D;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,GACnB,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAiC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,GACnB,IAAI,CA0BN;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,GACnB,IAAI,CAoBN;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAQ9E;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAa1E"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the event hook that manages session lifecycle and queue recovery.
|
|
3
|
+
*
|
|
4
|
+
* @param pipeline - Compression pipeline.
|
|
5
|
+
* @param config - Plugin configuration.
|
|
6
|
+
* @param state - Runtime state.
|
|
7
|
+
* @param logger - Structured logger.
|
|
8
|
+
* @returns Hook implementation.
|
|
9
|
+
*/
|
|
10
|
+
export function createEventHook(pipeline, config, state, logger) {
|
|
11
|
+
return async ({ event }) => {
|
|
12
|
+
if (isInternalEvent(event, state)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
switch (event.type) {
|
|
16
|
+
case "session.created": {
|
|
17
|
+
state.knownSessionIds.add(event.properties.info.id);
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
case "session.idle": {
|
|
21
|
+
scheduleSummary(event.properties.sessionID, pipeline, config, state, logger);
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
case "session.deleted": {
|
|
25
|
+
clearSummaryTimer(event.properties.info.id, state);
|
|
26
|
+
state.injectedSessionIds.delete(event.properties.info.id);
|
|
27
|
+
state.knownSessionIds.delete(event.properties.info.id);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
case "session.compacted": {
|
|
31
|
+
scheduleSummary(event.properties.sessionID, pipeline, config, state, logger);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
default:
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Registers a graceful shutdown handler once for the plugin process.
|
|
41
|
+
*
|
|
42
|
+
* @param pipeline - Compression pipeline.
|
|
43
|
+
* @param state - Runtime state.
|
|
44
|
+
* @param logger - Structured logger.
|
|
45
|
+
* @returns Nothing.
|
|
46
|
+
*/
|
|
47
|
+
export function registerShutdown(pipeline, state, logger) {
|
|
48
|
+
if (state.shutdownRegistered) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
state.shutdownRegistered = true;
|
|
52
|
+
const shutdown = async () => {
|
|
53
|
+
if (state.disposed) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
state.disposed = true;
|
|
57
|
+
try {
|
|
58
|
+
await pipeline.processQueue();
|
|
59
|
+
await logger.info("Memory plugin shutdown complete");
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
await logger.error("Memory plugin shutdown failed", {
|
|
63
|
+
error: error instanceof Error ? error.message : String(error),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
process.on("SIGTERM", () => void shutdown());
|
|
68
|
+
process.on("SIGINT", () => void shutdown());
|
|
69
|
+
process.on("beforeExit", () => void shutdown());
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Schedules summary generation after a debounce interval.
|
|
73
|
+
*
|
|
74
|
+
* @param sessionId - OpenCode session identifier.
|
|
75
|
+
* @param pipeline - Compression pipeline.
|
|
76
|
+
* @param config - Plugin configuration.
|
|
77
|
+
* @param state - Runtime state.
|
|
78
|
+
* @param logger - Structured logger.
|
|
79
|
+
* @returns Nothing.
|
|
80
|
+
*/
|
|
81
|
+
export function scheduleSummary(sessionId, pipeline, config, state, logger) {
|
|
82
|
+
clearSummaryTimer(sessionId, state);
|
|
83
|
+
const timer = setTimeout(() => {
|
|
84
|
+
void (async () => {
|
|
85
|
+
try {
|
|
86
|
+
await pipeline.flushSession(sessionId, 30_000);
|
|
87
|
+
await pipeline.generateSessionSummary(sessionId);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
await logger.warn("Failed to generate session summary", {
|
|
91
|
+
sessionId,
|
|
92
|
+
error: error instanceof Error ? error.message : String(error),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
clearSummaryTimer(sessionId, state);
|
|
97
|
+
}
|
|
98
|
+
})();
|
|
99
|
+
}, config.sessionSummaryDebounceMs);
|
|
100
|
+
state.summaryTimers.set(sessionId, timer);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Clears a scheduled summary timer.
|
|
104
|
+
*
|
|
105
|
+
* @param sessionId - OpenCode session identifier.
|
|
106
|
+
* @param state - Runtime state.
|
|
107
|
+
* @returns Nothing.
|
|
108
|
+
*/
|
|
109
|
+
export function clearSummaryTimer(sessionId, state) {
|
|
110
|
+
const timer = state.summaryTimers.get(sessionId);
|
|
111
|
+
if (!timer) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
clearTimeout(timer);
|
|
115
|
+
state.summaryTimers.delete(sessionId);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Checks whether an event belongs to an internal compressor session.
|
|
119
|
+
*
|
|
120
|
+
* @param event - OpenCode event.
|
|
121
|
+
* @param state - Runtime state.
|
|
122
|
+
* @returns True when the event should be ignored.
|
|
123
|
+
*/
|
|
124
|
+
export function isInternalEvent(event, state) {
|
|
125
|
+
switch (event.type) {
|
|
126
|
+
case "session.created":
|
|
127
|
+
case "session.updated":
|
|
128
|
+
case "session.deleted":
|
|
129
|
+
return state.internalSessionIds.has(event.properties.info.id);
|
|
130
|
+
case "session.idle":
|
|
131
|
+
case "session.compacted":
|
|
132
|
+
case "session.status":
|
|
133
|
+
return state.internalSessionIds.has(event.properties.sessionID);
|
|
134
|
+
default:
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/hooks/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Hooks } from "@opencode-ai/plugin";
|
|
2
|
+
import { MemoryStore } from "../storage/store";
|
|
3
|
+
import type { PluginConfig, RuntimeState } from "../types";
|
|
4
|
+
/**
|
|
5
|
+
* Creates the system prompt transform that injects memory context once per session.
|
|
6
|
+
*
|
|
7
|
+
* @param store - Memory store.
|
|
8
|
+
* @param config - Plugin configuration.
|
|
9
|
+
* @param state - Runtime state.
|
|
10
|
+
* @param now - Clock function.
|
|
11
|
+
* @returns Hook implementation.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createSystemTransformHook(store: MemoryStore, config: PluginConfig, state: RuntimeState, now: () => number): NonNullable<Hooks["experimental.chat.system.transform"]>;
|
|
14
|
+
//# sourceMappingURL=system-transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-transform.d.ts","sourceRoot":"","sources":["../../src/hooks/system-transform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAEhD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAE1D;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,GAAG,EAAE,MAAM,MAAM,GAChB,WAAW,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAe1D"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { generateSessionContext } from "../context/generator";
|
|
2
|
+
import { MemoryStore } from "../storage/store";
|
|
3
|
+
/**
|
|
4
|
+
* Creates the system prompt transform that injects memory context once per session.
|
|
5
|
+
*
|
|
6
|
+
* @param store - Memory store.
|
|
7
|
+
* @param config - Plugin configuration.
|
|
8
|
+
* @param state - Runtime state.
|
|
9
|
+
* @param now - Clock function.
|
|
10
|
+
* @returns Hook implementation.
|
|
11
|
+
*/
|
|
12
|
+
export function createSystemTransformHook(store, config, state, now) {
|
|
13
|
+
return async (input, output) => {
|
|
14
|
+
const sessionId = input.sessionID;
|
|
15
|
+
if (!sessionId || state.internalSessionIds.has(sessionId) || state.injectedSessionIds.has(sessionId)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const context = await generateSessionContext(store, config, now);
|
|
19
|
+
if (!context) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
output.system.unshift(context);
|
|
23
|
+
state.injectedSessionIds.add(sessionId);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=system-transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-transform.js","sourceRoot":"","sources":["../../src/hooks/system-transform.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAG9C;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAkB,EAClB,MAAoB,EACpB,KAAmB,EACnB,GAAiB;IAEjB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAC7B,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAA;QACjC,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACrG,OAAM;QACR,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;QAChE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAM;QACR,CAAC;QAED,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QAC9B,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACzC,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Hooks } from "@opencode-ai/plugin";
|
|
2
|
+
import { MemoryStore } from "../storage/store";
|
|
3
|
+
import type { MemoryLogger } from "../logger";
|
|
4
|
+
import type { CompressionPipeline } from "../compression/pipeline";
|
|
5
|
+
import type { PluginConfig, ProjectScope, RuntimeState } from "../types";
|
|
6
|
+
/**
|
|
7
|
+
* Creates the hook that captures tool outputs and enqueues them for compression.
|
|
8
|
+
*
|
|
9
|
+
* @param store - Memory store.
|
|
10
|
+
* @param pipeline - Compression pipeline.
|
|
11
|
+
* @param scope - Project scope.
|
|
12
|
+
* @param config - Plugin configuration.
|
|
13
|
+
* @param state - Runtime state.
|
|
14
|
+
* @param logger - Structured logger.
|
|
15
|
+
* @param now - Clock function.
|
|
16
|
+
* @returns Hook implementation.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createToolExecuteAfterHook(store: MemoryStore, pipeline: CompressionPipeline, scope: ProjectScope, config: PluginConfig, state: RuntimeState, logger: MemoryLogger, now: () => number): NonNullable<Hooks["tool.execute.after"]>;
|
|
19
|
+
/**
|
|
20
|
+
* Checks whether a tool output should be skipped from persistent memory capture.
|
|
21
|
+
*
|
|
22
|
+
* @param toolName - Executed tool name.
|
|
23
|
+
* @returns True when the tool is intentionally ignored.
|
|
24
|
+
*/
|
|
25
|
+
export declare function shouldIgnoreTool(toolName: string): boolean;
|
|
26
|
+
//# sourceMappingURL=tool-after.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-after.d.ts","sourceRoot":"","sources":["../../src/hooks/tool-after.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAC7C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAOxE;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,mBAAmB,EAC7B,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,YAAY,EACpB,GAAG,EAAE,MAAM,MAAM,GAChB,WAAW,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CA8D1C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAM1D"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { MemoryStore } from "../storage/store";
|
|
2
|
+
import { isProbablyBinary, normalizeWhitespace } from "../utils";
|
|
3
|
+
import { stripSensitiveTokens } from "../compression/privacy";
|
|
4
|
+
const IGNORED_TOOL_PREFIXES = ["memory_"];
|
|
5
|
+
const IGNORED_TOOL_NAMES = new Set(["todowrite"]);
|
|
6
|
+
/**
|
|
7
|
+
* Creates the hook that captures tool outputs and enqueues them for compression.
|
|
8
|
+
*
|
|
9
|
+
* @param store - Memory store.
|
|
10
|
+
* @param pipeline - Compression pipeline.
|
|
11
|
+
* @param scope - Project scope.
|
|
12
|
+
* @param config - Plugin configuration.
|
|
13
|
+
* @param state - Runtime state.
|
|
14
|
+
* @param logger - Structured logger.
|
|
15
|
+
* @param now - Clock function.
|
|
16
|
+
* @returns Hook implementation.
|
|
17
|
+
*/
|
|
18
|
+
export function createToolExecuteAfterHook(store, pipeline, scope, config, state, logger, now) {
|
|
19
|
+
return async (input, output) => {
|
|
20
|
+
if (state.internalSessionIds.has(input.sessionID)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (shouldIgnoreTool(input.tool)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const rawOutput = output.output ?? "";
|
|
27
|
+
if (!rawOutput || rawOutput.length < config.minContentLength) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (isProbablyBinary(rawOutput)) {
|
|
31
|
+
await logger.warn("Skipped binary-like tool output", {
|
|
32
|
+
tool: input.tool,
|
|
33
|
+
sessionId: input.sessionID,
|
|
34
|
+
});
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const content = config.privacyStrip ? stripSensitiveTokens(rawOutput) : rawOutput;
|
|
38
|
+
const truncated = content.slice(0, config.maxRawContentSize);
|
|
39
|
+
if (!normalizeWhitespace(truncated)) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
await store.enqueuePending({
|
|
44
|
+
id: store.createId(),
|
|
45
|
+
projectId: scope.projectId,
|
|
46
|
+
projectRoot: scope.projectRoot,
|
|
47
|
+
sessionId: input.sessionID,
|
|
48
|
+
toolName: input.tool,
|
|
49
|
+
title: output.title || null,
|
|
50
|
+
rawContent: truncated,
|
|
51
|
+
rawMetadata: {
|
|
52
|
+
callID: input.callID,
|
|
53
|
+
args: input.args,
|
|
54
|
+
metadata: output.metadata,
|
|
55
|
+
title: output.title,
|
|
56
|
+
},
|
|
57
|
+
status: "pending",
|
|
58
|
+
retryCount: 0,
|
|
59
|
+
errorMessage: null,
|
|
60
|
+
createdAt: now(),
|
|
61
|
+
processedAt: null,
|
|
62
|
+
});
|
|
63
|
+
queueMicrotask(() => {
|
|
64
|
+
void pipeline.processQueue();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
await logger.error("Failed to enqueue tool output", {
|
|
69
|
+
tool: input.tool,
|
|
70
|
+
sessionId: input.sessionID,
|
|
71
|
+
error: error instanceof Error ? error.message : String(error),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Checks whether a tool output should be skipped from persistent memory capture.
|
|
78
|
+
*
|
|
79
|
+
* @param toolName - Executed tool name.
|
|
80
|
+
* @returns True when the tool is intentionally ignored.
|
|
81
|
+
*/
|
|
82
|
+
export function shouldIgnoreTool(toolName) {
|
|
83
|
+
if (IGNORED_TOOL_NAMES.has(toolName)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return IGNORED_TOOL_PREFIXES.some((prefix) => toolName.startsWith(prefix));
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=tool-after.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-after.js","sourceRoot":"","sources":["../../src/hooks/tool-after.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
|
+
import type { MemoryPluginOptions } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Creates the OpenCode persistent memory plugin.
|
|
5
|
+
*
|
|
6
|
+
* @param options - Optional advanced overrides for testing or custom models.
|
|
7
|
+
* @returns A plugin function compatible with OpenCode.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createMemoryPlugin(options?: MemoryPluginOptions): Plugin;
|
|
10
|
+
export declare const MemoryPlugin: Plugin;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,qBAAqB,CAAA;AAiB9D,OAAO,KAAK,EAAE,mBAAmB,EAAgB,MAAM,SAAS,CAAA;AAEhE;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,CA6E5E;AAED,eAAO,MAAM,YAAY,EAAE,MAA6B,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { loadConfig } from "./config";
|
|
2
|
+
import { LanguageModelObservationCompressor, SessionPromptObservationCompressor } from "./compression/compressor";
|
|
3
|
+
import { CompressionPipeline } from "./compression/pipeline";
|
|
4
|
+
import { createCompactionHook } from "./hooks/compaction";
|
|
5
|
+
import { createEventHook, registerShutdown } from "./hooks/events";
|
|
6
|
+
import { createChatMessageHook } from "./hooks/chat-message";
|
|
7
|
+
import { createSystemTransformHook } from "./hooks/system-transform";
|
|
8
|
+
import { createToolExecuteAfterHook } from "./hooks/tool-after";
|
|
9
|
+
import { MemoryLogger } from "./logger";
|
|
10
|
+
import { createMemoryDatabase } from "./storage/db";
|
|
11
|
+
import { MemoryStore } from "./storage/store";
|
|
12
|
+
import { createMemoryGetTool } from "./tools/memory-get";
|
|
13
|
+
import { createMemoryForgetTool } from "./tools/memory-forget";
|
|
14
|
+
import { createMemorySearchTool } from "./tools/memory-search";
|
|
15
|
+
import { createMemoryStatsTool } from "./tools/memory-stats";
|
|
16
|
+
import { createMemoryTimelineTool } from "./tools/memory-timeline";
|
|
17
|
+
/**
|
|
18
|
+
* Creates the OpenCode persistent memory plugin.
|
|
19
|
+
*
|
|
20
|
+
* @param options - Optional advanced overrides for testing or custom models.
|
|
21
|
+
* @returns A plugin function compatible with OpenCode.
|
|
22
|
+
*/
|
|
23
|
+
export function createMemoryPlugin(options = {}) {
|
|
24
|
+
return async (input) => {
|
|
25
|
+
const now = options.now ?? Date.now;
|
|
26
|
+
const pluginConfig = await loadConfig({
|
|
27
|
+
directory: input.directory,
|
|
28
|
+
worktree: input.worktree,
|
|
29
|
+
});
|
|
30
|
+
const scope = {
|
|
31
|
+
projectId: input.project.id,
|
|
32
|
+
projectRoot: input.worktree,
|
|
33
|
+
directory: input.directory,
|
|
34
|
+
};
|
|
35
|
+
const database = await createMemoryDatabase(pluginConfig.dbPath);
|
|
36
|
+
const store = new MemoryStore(database, scope, now);
|
|
37
|
+
const logger = new MemoryLogger(input.client, input.directory, pluginConfig.logLevel);
|
|
38
|
+
const state = {
|
|
39
|
+
internalSessionIds: new Set(),
|
|
40
|
+
injectedSessionIds: new Set(),
|
|
41
|
+
knownSessionIds: new Set(),
|
|
42
|
+
summaryTimers: new Map(),
|
|
43
|
+
shutdownRegistered: false,
|
|
44
|
+
disposed: false,
|
|
45
|
+
};
|
|
46
|
+
const compressor = options.compressor ??
|
|
47
|
+
(options.languageModel
|
|
48
|
+
? new LanguageModelObservationCompressor(options.languageModel)
|
|
49
|
+
: new SessionPromptObservationCompressor(input, state));
|
|
50
|
+
const pipeline = new CompressionPipeline(store, compressor, input.client, input.directory, pluginConfig, logger, now);
|
|
51
|
+
await pipeline.recoverOrphans();
|
|
52
|
+
await store.cleanupOldData(pluginConfig.retentionDays);
|
|
53
|
+
queueMicrotask(() => {
|
|
54
|
+
void pipeline.processQueue();
|
|
55
|
+
});
|
|
56
|
+
registerShutdown(pipeline, state, logger);
|
|
57
|
+
void logger.info("Persistent memory plugin initialized", {
|
|
58
|
+
dbPath: pluginConfig.dbPath,
|
|
59
|
+
compressionModel: pluginConfig.compressionModel,
|
|
60
|
+
configPaths: pluginConfig.configPaths,
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
tool: {
|
|
64
|
+
memory_search: createMemorySearchTool(store, now),
|
|
65
|
+
memory_timeline: createMemoryTimelineTool(store),
|
|
66
|
+
memory_get: createMemoryGetTool(store),
|
|
67
|
+
memory_forget: createMemoryForgetTool(store, now),
|
|
68
|
+
memory_stats: createMemoryStatsTool(store, now),
|
|
69
|
+
},
|
|
70
|
+
event: createEventHook(pipeline, pluginConfig, state, logger),
|
|
71
|
+
"chat.message": createChatMessageHook(store, scope, state, now),
|
|
72
|
+
"tool.execute.after": createToolExecuteAfterHook(store, pipeline, scope, pluginConfig, state, logger, now),
|
|
73
|
+
"experimental.chat.system.transform": createSystemTransformHook(store, pluginConfig, state, now),
|
|
74
|
+
"experimental.session.compacting": createCompactionHook(store, state, now),
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
export const MemoryPlugin = createMemoryPlugin();
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { OpencodeClient } from "@opencode-ai/sdk";
|
|
2
|
+
import type { LogLevel } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Writes structured log entries through the OpenCode SDK client.
|
|
5
|
+
*/
|
|
6
|
+
export declare class MemoryLogger {
|
|
7
|
+
private readonly client;
|
|
8
|
+
private readonly directory;
|
|
9
|
+
private readonly level;
|
|
10
|
+
constructor(client: OpencodeClient, directory: string, level: LogLevel);
|
|
11
|
+
/**
|
|
12
|
+
* Writes a debug log entry.
|
|
13
|
+
*
|
|
14
|
+
* @param message - Human readable message.
|
|
15
|
+
* @param extra - Additional structured metadata.
|
|
16
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
17
|
+
*/
|
|
18
|
+
debug(message: string, extra?: Record<string, unknown>): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Writes an info log entry.
|
|
21
|
+
*
|
|
22
|
+
* @param message - Human readable message.
|
|
23
|
+
* @param extra - Additional structured metadata.
|
|
24
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
25
|
+
*/
|
|
26
|
+
info(message: string, extra?: Record<string, unknown>): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Writes a warning log entry.
|
|
29
|
+
*
|
|
30
|
+
* @param message - Human readable message.
|
|
31
|
+
* @param extra - Additional structured metadata.
|
|
32
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
33
|
+
*/
|
|
34
|
+
warn(message: string, extra?: Record<string, unknown>): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Writes an error log entry.
|
|
37
|
+
*
|
|
38
|
+
* @param message - Human readable message.
|
|
39
|
+
* @param extra - Additional structured metadata.
|
|
40
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
41
|
+
*/
|
|
42
|
+
error(message: string, extra?: Record<string, unknown>): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Writes a log entry if the requested level is enabled.
|
|
45
|
+
*
|
|
46
|
+
* @param level - Log level for the entry.
|
|
47
|
+
* @param message - Human readable message.
|
|
48
|
+
* @param extra - Additional structured metadata.
|
|
49
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
50
|
+
*/
|
|
51
|
+
write(level: LogLevel, message: string, extra?: Record<string, unknown>): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Checks whether a log level should be emitted.
|
|
54
|
+
*
|
|
55
|
+
* @param level - Candidate log level.
|
|
56
|
+
* @returns True when the entry should be logged.
|
|
57
|
+
*/
|
|
58
|
+
shouldLog(level: LogLevel): boolean;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AASvC;;GAEG;AACH,qBAAa,YAAY;IAErB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,QAAQ;IAGlC;;;;;;OAMG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5E;;;;;;OAMG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E;;;;;;OAMG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E;;;;;;OAMG;IACG,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5E;;;;;;;OAOG;IACG,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB7F;;;;;OAKG;IACH,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;CAGpC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const LEVEL_ORDER = {
|
|
2
|
+
debug: 10,
|
|
3
|
+
info: 20,
|
|
4
|
+
warn: 30,
|
|
5
|
+
error: 40,
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Writes structured log entries through the OpenCode SDK client.
|
|
9
|
+
*/
|
|
10
|
+
export class MemoryLogger {
|
|
11
|
+
client;
|
|
12
|
+
directory;
|
|
13
|
+
level;
|
|
14
|
+
constructor(client, directory, level) {
|
|
15
|
+
this.client = client;
|
|
16
|
+
this.directory = directory;
|
|
17
|
+
this.level = level;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Writes a debug log entry.
|
|
21
|
+
*
|
|
22
|
+
* @param message - Human readable message.
|
|
23
|
+
* @param extra - Additional structured metadata.
|
|
24
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
25
|
+
*/
|
|
26
|
+
async debug(message, extra) {
|
|
27
|
+
await this.write("debug", message, extra);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Writes an info log entry.
|
|
31
|
+
*
|
|
32
|
+
* @param message - Human readable message.
|
|
33
|
+
* @param extra - Additional structured metadata.
|
|
34
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
35
|
+
*/
|
|
36
|
+
async info(message, extra) {
|
|
37
|
+
await this.write("info", message, extra);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Writes a warning log entry.
|
|
41
|
+
*
|
|
42
|
+
* @param message - Human readable message.
|
|
43
|
+
* @param extra - Additional structured metadata.
|
|
44
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
45
|
+
*/
|
|
46
|
+
async warn(message, extra) {
|
|
47
|
+
await this.write("warn", message, extra);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Writes an error log entry.
|
|
51
|
+
*
|
|
52
|
+
* @param message - Human readable message.
|
|
53
|
+
* @param extra - Additional structured metadata.
|
|
54
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
55
|
+
*/
|
|
56
|
+
async error(message, extra) {
|
|
57
|
+
await this.write("error", message, extra);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Writes a log entry if the requested level is enabled.
|
|
61
|
+
*
|
|
62
|
+
* @param level - Log level for the entry.
|
|
63
|
+
* @param message - Human readable message.
|
|
64
|
+
* @param extra - Additional structured metadata.
|
|
65
|
+
* @returns A promise that resolves when the log attempt completes.
|
|
66
|
+
*/
|
|
67
|
+
async write(level, message, extra) {
|
|
68
|
+
if (!this.shouldLog(level)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
await this.client.app.log({
|
|
72
|
+
query: { directory: this.directory },
|
|
73
|
+
body: {
|
|
74
|
+
service: "plugin-memory",
|
|
75
|
+
level,
|
|
76
|
+
message,
|
|
77
|
+
extra,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Checks whether a log level should be emitted.
|
|
83
|
+
*
|
|
84
|
+
* @param level - Candidate log level.
|
|
85
|
+
* @returns True when the entry should be logged.
|
|
86
|
+
*/
|
|
87
|
+
shouldLog(level) {
|
|
88
|
+
return LEVEL_ORDER[level] >= LEVEL_ORDER[this.level];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,GAA6B;IAC5C,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;CACV,CAAA;AAED;;GAEG;AACH,MAAM,OAAO,YAAY;IAEJ;IACA;IACA;IAHnB,YACmB,MAAsB,EACtB,SAAiB,EACjB,KAAe;QAFf,WAAM,GAAN,MAAM,CAAgB;QACtB,cAAS,GAAT,SAAS,CAAQ;QACjB,UAAK,GAAL,KAAK,CAAU;IAC/B,CAAC;IAEJ;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,KAA+B;QAC1D,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,KAA+B;QACzD,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;IAC1C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,IAAI,CAAC,OAAe,EAAE,KAA+B;QACzD,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;IAC1C,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,KAA+B;QAC1D,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAA;IAC3C,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,KAAK,CAAC,KAAe,EAAE,OAAe,EAAE,KAA+B;QAC3E,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAM;QACR,CAAC;QAED,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;YACxB,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;YACpC,IAAI,EAAE;gBACJ,OAAO,EAAE,eAAe;gBACxB,KAAK;gBACL,OAAO;gBACP,KAAK;aACN;SACF,CAAC,CAAA;IACJ,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,KAAe;QACvB,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACtD,CAAC;CACF"}
|