opencode-graphiti 0.0.0-development
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/LICENSE +21 -0
- package/README.md +358 -0
- package/esm/_dnt.polyfills.d.ts +166 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +177 -0
- package/esm/_dnt.shims.d.ts +6 -0
- package/esm/_dnt.shims.d.ts.map +1 -0
- package/esm/_dnt.shims.js +61 -0
- package/esm/deno.d.ts +45 -0
- package/esm/deno.d.ts.map +1 -0
- package/esm/deno.js +39 -0
- package/esm/mod.d.ts +3 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +2 -0
- package/esm/package.json +3 -0
- package/esm/src/config.d.ts +20 -0
- package/esm/src/config.d.ts.map +1 -0
- package/esm/src/config.js +246 -0
- package/esm/src/handlers/chat.d.ts +14 -0
- package/esm/src/handlers/chat.d.ts.map +1 -0
- package/esm/src/handlers/chat.js +60 -0
- package/esm/src/handlers/compacting.d.ts +9 -0
- package/esm/src/handlers/compacting.d.ts.map +1 -0
- package/esm/src/handlers/compacting.js +30 -0
- package/esm/src/handlers/event.d.ts +22 -0
- package/esm/src/handlers/event.d.ts.map +1 -0
- package/esm/src/handlers/event.js +287 -0
- package/esm/src/handlers/messages.d.ts +9 -0
- package/esm/src/handlers/messages.d.ts.map +1 -0
- package/esm/src/handlers/messages.js +93 -0
- package/esm/src/index.d.ts +5 -0
- package/esm/src/index.d.ts.map +1 -0
- package/esm/src/index.js +153 -0
- package/esm/src/services/batch-drain.d.ts +23 -0
- package/esm/src/services/batch-drain.d.ts.map +1 -0
- package/esm/src/services/batch-drain.js +217 -0
- package/esm/src/services/connection-manager.d.ts +104 -0
- package/esm/src/services/connection-manager.d.ts.map +1 -0
- package/esm/src/services/connection-manager.js +621 -0
- package/esm/src/services/constants.d.ts +7 -0
- package/esm/src/services/constants.d.ts.map +1 -0
- package/esm/src/services/constants.js +6 -0
- package/esm/src/services/context-limit.d.ts +3 -0
- package/esm/src/services/context-limit.d.ts.map +1 -0
- package/esm/src/services/context-limit.js +44 -0
- package/esm/src/services/event-extractor.d.ts +29 -0
- package/esm/src/services/event-extractor.d.ts.map +1 -0
- package/esm/src/services/event-extractor.js +659 -0
- package/esm/src/services/graphiti-async.d.ts +22 -0
- package/esm/src/services/graphiti-async.d.ts.map +1 -0
- package/esm/src/services/graphiti-async.js +219 -0
- package/esm/src/services/graphiti-mcp.d.ts +57 -0
- package/esm/src/services/graphiti-mcp.d.ts.map +1 -0
- package/esm/src/services/graphiti-mcp.js +194 -0
- package/esm/src/services/logger.d.ts +9 -0
- package/esm/src/services/logger.d.ts.map +1 -0
- package/esm/src/services/logger.js +104 -0
- package/esm/src/services/opencode-warning.d.ts +8 -0
- package/esm/src/services/opencode-warning.d.ts.map +1 -0
- package/esm/src/services/opencode-warning.js +104 -0
- package/esm/src/services/redis-cache.d.ts +27 -0
- package/esm/src/services/redis-cache.d.ts.map +1 -0
- package/esm/src/services/redis-cache.js +215 -0
- package/esm/src/services/redis-client.d.ts +89 -0
- package/esm/src/services/redis-client.d.ts.map +1 -0
- package/esm/src/services/redis-client.js +906 -0
- package/esm/src/services/redis-events.d.ts +46 -0
- package/esm/src/services/redis-events.d.ts.map +1 -0
- package/esm/src/services/redis-events.js +517 -0
- package/esm/src/services/redis-snapshot.d.ts +16 -0
- package/esm/src/services/redis-snapshot.d.ts.map +1 -0
- package/esm/src/services/redis-snapshot.js +184 -0
- package/esm/src/services/render-utils.d.ts +23 -0
- package/esm/src/services/render-utils.d.ts.map +1 -0
- package/esm/src/services/render-utils.js +149 -0
- package/esm/src/services/runtime-teardown.d.ts +23 -0
- package/esm/src/services/runtime-teardown.d.ts.map +1 -0
- package/esm/src/services/runtime-teardown.js +119 -0
- package/esm/src/services/sdk-normalize.d.ts +55 -0
- package/esm/src/services/sdk-normalize.d.ts.map +1 -0
- package/esm/src/services/sdk-normalize.js +61 -0
- package/esm/src/session.d.ts +74 -0
- package/esm/src/session.d.ts.map +1 -0
- package/esm/src/session.js +694 -0
- package/esm/src/types/index.d.ts +120 -0
- package/esm/src/types/index.d.ts.map +1 -0
- package/esm/src/types/index.js +28 -0
- package/esm/src/utils.d.ts +27 -0
- package/esm/src/utils.d.ts.map +1 -0
- package/esm/src/utils.js +76 -0
- package/package.json +59 -0
- package/script/_dnt.polyfills.d.ts +166 -0
- package/script/_dnt.polyfills.d.ts.map +1 -0
- package/script/_dnt.polyfills.js +180 -0
- package/script/_dnt.shims.d.ts +6 -0
- package/script/_dnt.shims.d.ts.map +1 -0
- package/script/_dnt.shims.js +65 -0
- package/script/deno.d.ts +45 -0
- package/script/deno.d.ts.map +1 -0
- package/script/deno.js +41 -0
- package/script/mod.d.ts +3 -0
- package/script/mod.d.ts.map +1 -0
- package/script/mod.js +6 -0
- package/script/package.json +3 -0
- package/script/src/config.d.ts +20 -0
- package/script/src/config.d.ts.map +1 -0
- package/script/src/config.js +256 -0
- package/script/src/handlers/chat.d.ts +14 -0
- package/script/src/handlers/chat.d.ts.map +1 -0
- package/script/src/handlers/chat.js +63 -0
- package/script/src/handlers/compacting.d.ts +9 -0
- package/script/src/handlers/compacting.d.ts.map +1 -0
- package/script/src/handlers/compacting.js +33 -0
- package/script/src/handlers/event.d.ts +22 -0
- package/script/src/handlers/event.d.ts.map +1 -0
- package/script/src/handlers/event.js +290 -0
- package/script/src/handlers/messages.d.ts +9 -0
- package/script/src/handlers/messages.d.ts.map +1 -0
- package/script/src/handlers/messages.js +96 -0
- package/script/src/index.d.ts +5 -0
- package/script/src/index.d.ts.map +1 -0
- package/script/src/index.js +159 -0
- package/script/src/services/batch-drain.d.ts +23 -0
- package/script/src/services/batch-drain.d.ts.map +1 -0
- package/script/src/services/batch-drain.js +221 -0
- package/script/src/services/connection-manager.d.ts +104 -0
- package/script/src/services/connection-manager.d.ts.map +1 -0
- package/script/src/services/connection-manager.js +635 -0
- package/script/src/services/constants.d.ts +7 -0
- package/script/src/services/constants.d.ts.map +1 -0
- package/script/src/services/constants.js +9 -0
- package/script/src/services/context-limit.d.ts +3 -0
- package/script/src/services/context-limit.d.ts.map +1 -0
- package/script/src/services/context-limit.js +47 -0
- package/script/src/services/event-extractor.d.ts +29 -0
- package/script/src/services/event-extractor.d.ts.map +1 -0
- package/script/src/services/event-extractor.js +669 -0
- package/script/src/services/graphiti-async.d.ts +22 -0
- package/script/src/services/graphiti-async.d.ts.map +1 -0
- package/script/src/services/graphiti-async.js +223 -0
- package/script/src/services/graphiti-mcp.d.ts +57 -0
- package/script/src/services/graphiti-mcp.d.ts.map +1 -0
- package/script/src/services/graphiti-mcp.js +198 -0
- package/script/src/services/logger.d.ts +9 -0
- package/script/src/services/logger.d.ts.map +1 -0
- package/script/src/services/logger.js +142 -0
- package/script/src/services/opencode-warning.d.ts +8 -0
- package/script/src/services/opencode-warning.d.ts.map +1 -0
- package/script/src/services/opencode-warning.js +114 -0
- package/script/src/services/redis-cache.d.ts +27 -0
- package/script/src/services/redis-cache.d.ts.map +1 -0
- package/script/src/services/redis-cache.js +219 -0
- package/script/src/services/redis-client.d.ts +89 -0
- package/script/src/services/redis-client.d.ts.map +1 -0
- package/script/src/services/redis-client.js +943 -0
- package/script/src/services/redis-events.d.ts +46 -0
- package/script/src/services/redis-events.d.ts.map +1 -0
- package/script/src/services/redis-events.js +535 -0
- package/script/src/services/redis-snapshot.d.ts +16 -0
- package/script/src/services/redis-snapshot.d.ts.map +1 -0
- package/script/src/services/redis-snapshot.js +189 -0
- package/script/src/services/render-utils.d.ts +23 -0
- package/script/src/services/render-utils.d.ts.map +1 -0
- package/script/src/services/render-utils.js +165 -0
- package/script/src/services/runtime-teardown.d.ts +23 -0
- package/script/src/services/runtime-teardown.d.ts.map +1 -0
- package/script/src/services/runtime-teardown.js +155 -0
- package/script/src/services/sdk-normalize.d.ts +55 -0
- package/script/src/services/sdk-normalize.d.ts.map +1 -0
- package/script/src/services/sdk-normalize.js +67 -0
- package/script/src/session.d.ts +74 -0
- package/script/src/session.d.ts.map +1 -0
- package/script/src/session.js +698 -0
- package/script/src/types/index.d.ts +120 -0
- package/script/src/types/index.d.ts.map +1 -0
- package/script/src/types/index.js +33 -0
- package/script/src/utils.d.ts +27 -0
- package/script/src/utils.d.ts.map +1 -0
- package/script/src/utils.js +87 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { getSessionEventPrimaryText, } from "../types/index.js";
|
|
2
|
+
import { sessionSnapshotKey } from "./redis-events.js";
|
|
3
|
+
import { escapeXml, normalizeMemoryText, renderXmlListSection, renderXmlSingleSection, sanitizeMemoryInput, uniqueNormalizedValues, } from "./render-utils.js";
|
|
4
|
+
const SNAPSHOT_BUDGET = 3_000;
|
|
5
|
+
const BLOCKER_PATTERN = /\b(blocker|blocked|blocking)\b/i;
|
|
6
|
+
const selectRecent = (events, predicate, map, limit, excludedNormalized = new Set()) => uniqueNormalizedValues(events.flatMap((event) => {
|
|
7
|
+
if (!predicate(event))
|
|
8
|
+
return [];
|
|
9
|
+
const value = map(event);
|
|
10
|
+
if (!value)
|
|
11
|
+
return [];
|
|
12
|
+
return Array.isArray(value) ? value : [value];
|
|
13
|
+
}).reverse(), limit, excludedNormalized);
|
|
14
|
+
export const buildSessionSnapshotXml = (sessionId, events) => {
|
|
15
|
+
const decisions = selectRecent(events, (event) => ["decision", "preference"].includes(event.category), (event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)), 5);
|
|
16
|
+
const occupiedNormalized = new Set(decisions.map((value) => normalizeMemoryText(value)).filter(Boolean));
|
|
17
|
+
const constraints = selectRecent(events, (event) => event.category === "rule.load", (event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)), 5, occupiedNormalized);
|
|
18
|
+
for (const value of constraints) {
|
|
19
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
20
|
+
}
|
|
21
|
+
const latestUserRequest = getSessionEventPrimaryText(events.findLast((event) => event.role === "user") ?? {
|
|
22
|
+
id: "",
|
|
23
|
+
ts: 0,
|
|
24
|
+
category: "message",
|
|
25
|
+
priority: 4,
|
|
26
|
+
role: "user",
|
|
27
|
+
summary: "",
|
|
28
|
+
}) || undefined;
|
|
29
|
+
const sanitizedLatestUserRequest = latestUserRequest
|
|
30
|
+
? sanitizeMemoryInput(latestUserRequest)
|
|
31
|
+
: undefined;
|
|
32
|
+
const normalizedLatestUserRequest = sanitizedLatestUserRequest
|
|
33
|
+
? normalizeMemoryText(sanitizedLatestUserRequest)
|
|
34
|
+
: "";
|
|
35
|
+
if (normalizedLatestUserRequest) {
|
|
36
|
+
occupiedNormalized.add(normalizedLatestUserRequest);
|
|
37
|
+
}
|
|
38
|
+
const activeTask = events.findLast((event) => ["task.create", "task.update", "task.complete"].includes(event.category))?.summary;
|
|
39
|
+
const sanitizedActiveTask = sanitizeMemoryInput(activeTask ?? "");
|
|
40
|
+
const activeTaskValue = sanitizedActiveTask &&
|
|
41
|
+
normalizeMemoryText(sanitizedActiveTask) !== normalizedLatestUserRequest
|
|
42
|
+
? sanitizedActiveTask
|
|
43
|
+
: undefined;
|
|
44
|
+
if (activeTaskValue) {
|
|
45
|
+
occupiedNormalized.add(normalizeMemoryText(activeTaskValue));
|
|
46
|
+
}
|
|
47
|
+
const activeFiles = selectRecent(events, (event) => event.category.startsWith("file."), (event) => event.refs ?? [], 6, occupiedNormalized);
|
|
48
|
+
for (const value of activeFiles) {
|
|
49
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
50
|
+
}
|
|
51
|
+
const recentEdits = selectRecent(events, (event) => event.category === "file.write" || event.category === "file.edit", (event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)), 5, occupiedNormalized);
|
|
52
|
+
for (const value of recentEdits) {
|
|
53
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
54
|
+
}
|
|
55
|
+
const subagentsOpen = selectRecent(events, (event) => event.category === "subagent.start", (event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)), 4, occupiedNormalized);
|
|
56
|
+
for (const value of subagentsOpen) {
|
|
57
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
58
|
+
}
|
|
59
|
+
const unresolvedErrors = events.filter((event) => event.category === "error" && event.metadata?.resolved !== true &&
|
|
60
|
+
event.role !== "assistant");
|
|
61
|
+
const errors = uniqueNormalizedValues(unresolvedErrors.map((event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)))
|
|
62
|
+
.reverse(), 4, occupiedNormalized);
|
|
63
|
+
for (const value of errors) {
|
|
64
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
65
|
+
}
|
|
66
|
+
const blockers = uniqueNormalizedValues(unresolvedErrors.flatMap((event) => {
|
|
67
|
+
const blockerText = sanitizeMemoryInput(event.detail?.trim() ||
|
|
68
|
+
event.continuityText?.trim() ||
|
|
69
|
+
event.body?.trim() || "");
|
|
70
|
+
if (!blockerText || blockerText === event.summary)
|
|
71
|
+
return [];
|
|
72
|
+
if (event.metadata?.blocking === true ||
|
|
73
|
+
BLOCKER_PATTERN.test(blockerText) ||
|
|
74
|
+
BLOCKER_PATTERN.test(event.summary)) {
|
|
75
|
+
return [blockerText];
|
|
76
|
+
}
|
|
77
|
+
return [];
|
|
78
|
+
}).reverse(), 3, occupiedNormalized);
|
|
79
|
+
for (const value of blockers) {
|
|
80
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
81
|
+
}
|
|
82
|
+
const environment = selectRecent(events, (event) => event.category === "cwd.change" || event.category === "env.change", (event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)), 4, occupiedNormalized);
|
|
83
|
+
for (const value of environment) {
|
|
84
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
85
|
+
}
|
|
86
|
+
const gitState = selectRecent(events, (event) => event.category === "git.activity", (event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)), 4, occupiedNormalized);
|
|
87
|
+
for (const value of gitState) {
|
|
88
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
89
|
+
}
|
|
90
|
+
const subagentsDone = selectRecent(events, (event) => event.category === "subagent.finish", (event) => sanitizeMemoryInput(getSessionEventPrimaryText(event)), 4, occupiedNormalized);
|
|
91
|
+
for (const value of subagentsDone) {
|
|
92
|
+
occupiedNormalized.add(normalizeMemoryText(value));
|
|
93
|
+
}
|
|
94
|
+
const open = `<snapshot session="${escapeXml(sessionId)}" ts="${Date.now()}" version="2">`;
|
|
95
|
+
const close = `</snapshot>`;
|
|
96
|
+
let xml = open;
|
|
97
|
+
let remaining = SNAPSHOT_BUDGET - open.length - close.length;
|
|
98
|
+
const sectionBuilders = [
|
|
99
|
+
() => renderXmlListSection("decisions", "d", decisions, {
|
|
100
|
+
itemCharLimit: 240,
|
|
101
|
+
remaining,
|
|
102
|
+
}),
|
|
103
|
+
() => renderXmlListSection("constraints", "c", constraints, {
|
|
104
|
+
itemCharLimit: 240,
|
|
105
|
+
remaining,
|
|
106
|
+
}),
|
|
107
|
+
() => renderXmlSingleSection("active_task", "goal", activeTaskValue, {
|
|
108
|
+
valueCharLimit: 320,
|
|
109
|
+
remaining,
|
|
110
|
+
}),
|
|
111
|
+
() => renderXmlListSection("active_files", "f", activeFiles, {
|
|
112
|
+
itemCharLimit: 240,
|
|
113
|
+
remaining,
|
|
114
|
+
}),
|
|
115
|
+
() => renderXmlListSection("recent_edits", "e", recentEdits, {
|
|
116
|
+
itemCharLimit: 220,
|
|
117
|
+
remaining,
|
|
118
|
+
}),
|
|
119
|
+
() => renderXmlListSection("subagents_open", "s", subagentsOpen, {
|
|
120
|
+
itemCharLimit: 220,
|
|
121
|
+
remaining,
|
|
122
|
+
}),
|
|
123
|
+
() => renderXmlListSection("errors", "e", errors, {
|
|
124
|
+
itemCharLimit: 240,
|
|
125
|
+
remaining,
|
|
126
|
+
}),
|
|
127
|
+
() => renderXmlListSection("blockers", "b", blockers, {
|
|
128
|
+
itemCharLimit: 220,
|
|
129
|
+
remaining,
|
|
130
|
+
}),
|
|
131
|
+
() => renderXmlListSection("environment", "e", environment, {
|
|
132
|
+
itemCharLimit: 240,
|
|
133
|
+
remaining,
|
|
134
|
+
}),
|
|
135
|
+
() => renderXmlListSection("git_state", "g", gitState, {
|
|
136
|
+
itemCharLimit: 220,
|
|
137
|
+
remaining,
|
|
138
|
+
}),
|
|
139
|
+
() => renderXmlListSection("subagents_done", "s", subagentsDone, {
|
|
140
|
+
itemCharLimit: 220,
|
|
141
|
+
remaining,
|
|
142
|
+
}),
|
|
143
|
+
];
|
|
144
|
+
for (const buildSection of sectionBuilders) {
|
|
145
|
+
const section = buildSection();
|
|
146
|
+
if (!section)
|
|
147
|
+
continue;
|
|
148
|
+
if (section.length > remaining)
|
|
149
|
+
break;
|
|
150
|
+
xml += section;
|
|
151
|
+
remaining -= section.length;
|
|
152
|
+
}
|
|
153
|
+
return `${xml}${close}`;
|
|
154
|
+
};
|
|
155
|
+
export class RedisSnapshotService {
|
|
156
|
+
constructor(redis, options) {
|
|
157
|
+
Object.defineProperty(this, "redis", {
|
|
158
|
+
enumerable: true,
|
|
159
|
+
configurable: true,
|
|
160
|
+
writable: true,
|
|
161
|
+
value: redis
|
|
162
|
+
});
|
|
163
|
+
Object.defineProperty(this, "options", {
|
|
164
|
+
enumerable: true,
|
|
165
|
+
configurable: true,
|
|
166
|
+
writable: true,
|
|
167
|
+
value: options
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
async getSnapshot(sessionId) {
|
|
171
|
+
return await this.redis.getString(sessionSnapshotKey(sessionId));
|
|
172
|
+
}
|
|
173
|
+
async saveSnapshot(sessionId, snapshot) {
|
|
174
|
+
await this.redis.setString(sessionSnapshotKey(sessionId), snapshot, this.options.ttlSeconds);
|
|
175
|
+
}
|
|
176
|
+
async touchSnapshot(sessionId) {
|
|
177
|
+
await this.redis.touch(sessionSnapshotKey(sessionId), this.options.ttlSeconds);
|
|
178
|
+
}
|
|
179
|
+
async rebuildAndSave(sessionId, events) {
|
|
180
|
+
const snapshot = buildSessionSnapshotXml(sessionId, events);
|
|
181
|
+
await this.saveSnapshot(sessionId, snapshot);
|
|
182
|
+
return snapshot;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const escapeXml: (value: string) => string;
|
|
2
|
+
export declare const stripInjectedMemoryBlocks: (value: string) => string;
|
|
3
|
+
export declare const stripToolTranscriptWrappers: (value: string) => string;
|
|
4
|
+
export declare const sanitizeMemoryInput: (value: string) => string;
|
|
5
|
+
export declare const sanitizeMemoryInputPreservingMemoryBlocks: (value: string) => string;
|
|
6
|
+
export declare const normalizeMemoryText: (value: string) => string;
|
|
7
|
+
export declare const uniqueNormalizedValues: (values: string[], limit: number, excludedNormalized?: Set<string>) => string[];
|
|
8
|
+
export declare const looksLikeOperationalChatter: (value: string) => boolean;
|
|
9
|
+
export declare const looksLikeToolTranscript: (value: string) => boolean;
|
|
10
|
+
export declare const looksTranscriptHeavy: (value: string) => boolean;
|
|
11
|
+
export declare const isHighValueMemoryText: (value: string) => boolean;
|
|
12
|
+
export interface RenderXmlListSectionOptions {
|
|
13
|
+
itemCharLimit?: number;
|
|
14
|
+
remaining?: number;
|
|
15
|
+
includeEmpty?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const renderXmlListSection: (tag: string, itemTag: string, values: string[], options?: RenderXmlListSectionOptions) => string;
|
|
18
|
+
export interface RenderXmlSingleSectionOptions {
|
|
19
|
+
valueCharLimit?: number;
|
|
20
|
+
remaining?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const renderXmlSingleSection: (tag: string, itemTag: string, value: string | undefined, options?: RenderXmlSingleSectionOptions) => string;
|
|
23
|
+
//# sourceMappingURL=render-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-utils.d.ts","sourceRoot":"","sources":["../../../src/src/services/render-utils.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,GAAI,OAAO,MAAM,KAAG,MAKZ,CAAC;AA4B/B,eAAO,MAAM,yBAAyB,GAAI,OAAO,MAAM,KAAG,MAGR,CAAC;AAEnD,eAAO,MAAM,2BAA2B,GAAI,OAAO,MAAM,KAAG,MAKjD,CAAC;AASZ,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,KAAG,MAGjD,CAAC;AAEJ,eAAO,MAAM,yCAAyC,GACpD,OAAO,MAAM,KACZ,MAAoE,CAAC;AAExE,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,KAAG,MAMzC,CAAC;AAEZ,eAAO,MAAM,sBAAsB,GACjC,QAAQ,MAAM,EAAE,EAChB,OAAO,MAAM,EACb,gCAAsC,KACrC,MAAM,EAiBR,CAAC;AAEF,eAAO,MAAM,2BAA2B,GAAI,OAAO,MAAM,KAAG,OACE,CAAC;AAE/D,eAAO,MAAM,uBAAuB,GAAI,OAAO,MAAM,KAAG,OAEnB,CAAC;AAEtC,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,KAAG,OAKpD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,OAAO,MAAM,KAAG,OAcrD,CAAC;AAqBF,MAAM,WAAW,2BAA2B;IAC1C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,oBAAoB,GAC/B,KAAK,MAAM,EACX,SAAS,MAAM,EACf,QAAQ,MAAM,EAAE,EAChB,UAAS,2BAAgC,KACxC,MA+BF,CAAC;AAEF,MAAM,WAAW,6BAA6B;IAC5C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,sBAAsB,GACjC,KAAK,MAAM,EACX,SAAS,MAAM,EACf,OAAO,MAAM,GAAG,SAAS,EACzB,UAAS,6BAAkC,KAC1C,MAmBF,CAAC"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export const escapeXml = (value) => value.replaceAll("&", "&")
|
|
2
|
+
.replaceAll("<", "<")
|
|
3
|
+
.replaceAll(">", ">")
|
|
4
|
+
.replaceAll('"', """)
|
|
5
|
+
.replaceAll("'", "'");
|
|
6
|
+
const SESSION_MEMORY_BLOCK_PATTERN = /<session_memory\b[^>]*>[\s\S]*?<\/session_memory>/gi;
|
|
7
|
+
const LEGACY_MEMORY_BLOCK_PATTERN = /<memory\b[^>]*>[\s\S]*?<\/memory>/gi;
|
|
8
|
+
const PERSISTENT_MEMORY_BLOCK_PATTERN = /<persistent_memory\b[^>]*>[\s\S]*?<\/persistent_memory>/gi;
|
|
9
|
+
const TOOL_WRAPPER_DOCUMENT_PATTERN = /^\s*(?:<(?:path|content|type)\b[^>]*>[\s\S]*?<\/(?:path|content|type)>\s*)+$/i;
|
|
10
|
+
const TOOL_WRAPPER_BLOCK_PATTERN = /<(?:path|content|type)\b[^>]*>[\s\S]*?<\/(?:path|content|type)>/gi;
|
|
11
|
+
const TOOL_WRAPPER_LINE_PATTERN = /^\s*<\/?(?:path|content|type)\b[^>]*>\s*$/gim;
|
|
12
|
+
const TOOL_WRAPPER_PREFIX_PATTERN = /^\s*(?:<path>|<content>|<type>|<path\b[^>]*>|<content\b[^>]*>|<type\b[^>]*>|<\/path>|<\/content>|<\/type>|<path>.*<\/path>|<type>.*<\/type>|\d+:\s*<(?:path|content|type)\b[^>]*>)\s*$/gim;
|
|
13
|
+
const TOOL_TRANSCRIPT_PATTERN = /\b(?:tool(?:_use)?s?|orchestration|delegat(?:e|ed|ion)|subagent|wrapper|transcript|read output|read wrapper|session_memory|persistent_memory)\b/i;
|
|
14
|
+
const OPERATIONAL_CHATTER_PATTERN = /^(?:plan per target:|i(?:'m| am| will| can| should| need to)\b|now\b.*\b(?:checking|reading|inspecting|updating|running)|next\b.*\b(?:checking|reading|updating|running))/i;
|
|
15
|
+
const LOW_VALUE_MEMORY_PATTERN = /\b(?:assistant|meta chatter|planning chatter|phrasing suggestion|tool routing|orchestration|delegate|subagent|wrapper)\b/i;
|
|
16
|
+
const HIGH_VALUE_MEMORY_PATTERN = /\b(?:architecture|decision|constraint|prefer|preference|must|should|rule|policy|hot path|async|graphiti|redis|falkordb|session memory|persistent memory|milestone|file|src\/|plans\/|docs\/|fix|implement|update)\b/i;
|
|
17
|
+
const TRANSCRIPT_HEAVY_PATTERN = /```|(?:^|\n)\d+:\s|(?:^|\n)\$\s|\b(?:stdout|stderr|exit code|tool output|read output|file contents|transcript)\b/i;
|
|
18
|
+
const STRUCTURED_TRANSCRIPT_HEAVY_PATTERN = /```|(?:^|\n)\d+:\s|(?:^|\n)\$\s|\b(?:stdout|stderr|exit code|tool output|read output|file contents)\b/i;
|
|
19
|
+
export const stripInjectedMemoryBlocks = (value) => value.replace(SESSION_MEMORY_BLOCK_PATTERN, " ")
|
|
20
|
+
.replace(LEGACY_MEMORY_BLOCK_PATTERN, " ")
|
|
21
|
+
.replace(PERSISTENT_MEMORY_BLOCK_PATTERN, " ");
|
|
22
|
+
export const stripToolTranscriptWrappers = (value) => TOOL_WRAPPER_DOCUMENT_PATTERN.test(value)
|
|
23
|
+
? value.replace(TOOL_WRAPPER_BLOCK_PATTERN, " ")
|
|
24
|
+
.replace(TOOL_WRAPPER_LINE_PATTERN, " ")
|
|
25
|
+
.replace(TOOL_WRAPPER_PREFIX_PATTERN, " ")
|
|
26
|
+
: value;
|
|
27
|
+
const normalizeSanitizedText = (value) => value.replace(/\r\n/g, "\n")
|
|
28
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
29
|
+
.replace(/[\t ]+/g, " ")
|
|
30
|
+
.replace(/ ?\n ?/g, "\n")
|
|
31
|
+
.trim();
|
|
32
|
+
export const sanitizeMemoryInput = (value) => normalizeSanitizedText(stripToolTranscriptWrappers(stripInjectedMemoryBlocks(value)));
|
|
33
|
+
export const sanitizeMemoryInputPreservingMemoryBlocks = (value) => normalizeSanitizedText(stripToolTranscriptWrappers(value));
|
|
34
|
+
export const normalizeMemoryText = (value) => sanitizeMemoryInput(value)
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.replace(/&(?:amp|lt|gt|quot|apos);/g, " ")
|
|
37
|
+
.replace(/[^a-z0-9./_-]+/g, " ")
|
|
38
|
+
.replace(/\s+/g, " ")
|
|
39
|
+
.trim();
|
|
40
|
+
export const uniqueNormalizedValues = (values, limit, excludedNormalized = new Set()) => {
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
const result = [];
|
|
43
|
+
for (const value of values) {
|
|
44
|
+
const cleaned = sanitizeMemoryInput(value);
|
|
45
|
+
const normalized = normalizeMemoryText(cleaned);
|
|
46
|
+
if (!cleaned || !normalized || excludedNormalized.has(normalized) ||
|
|
47
|
+
seen.has(normalized)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
seen.add(normalized);
|
|
51
|
+
result.push(cleaned);
|
|
52
|
+
if (result.length >= limit)
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
};
|
|
57
|
+
export const looksLikeOperationalChatter = (value) => OPERATIONAL_CHATTER_PATTERN.test(sanitizeMemoryInput(value));
|
|
58
|
+
export const looksLikeToolTranscript = (value) => TOOL_WRAPPER_DOCUMENT_PATTERN.test(value) ||
|
|
59
|
+
TOOL_TRANSCRIPT_PATTERN.test(value);
|
|
60
|
+
export const looksTranscriptHeavy = (value) => {
|
|
61
|
+
const sanitized = sanitizeMemoryInput(value);
|
|
62
|
+
if (!sanitized)
|
|
63
|
+
return false;
|
|
64
|
+
return sanitized.length > 600 || sanitized.split("\n").length > 12 ||
|
|
65
|
+
TRANSCRIPT_HEAVY_PATTERN.test(sanitized);
|
|
66
|
+
};
|
|
67
|
+
export const isHighValueMemoryText = (value) => {
|
|
68
|
+
const sanitized = sanitizeMemoryInput(value);
|
|
69
|
+
if (!sanitized)
|
|
70
|
+
return false;
|
|
71
|
+
const looksHighValue = HIGH_VALUE_MEMORY_PATTERN.test(sanitized);
|
|
72
|
+
if (!looksHighValue)
|
|
73
|
+
return false;
|
|
74
|
+
const hasStructuredTranscriptEvidence = TOOL_WRAPPER_DOCUMENT_PATTERN.test(value) || sanitized.length > 600 ||
|
|
75
|
+
sanitized.split("\n").length > 12 ||
|
|
76
|
+
STRUCTURED_TRANSCRIPT_HEAVY_PATTERN.test(sanitized);
|
|
77
|
+
if (looksLikeToolTranscript(sanitized) && hasStructuredTranscriptEvidence) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
if (LOW_VALUE_MEMORY_PATTERN.test(sanitized))
|
|
81
|
+
return false;
|
|
82
|
+
return true;
|
|
83
|
+
};
|
|
84
|
+
const fitEscapedText = (value, maxEscapedLength) => {
|
|
85
|
+
const source = value.trim();
|
|
86
|
+
if (!source || maxEscapedLength <= 0)
|
|
87
|
+
return "";
|
|
88
|
+
if (escapeXml(source).length <= maxEscapedLength)
|
|
89
|
+
return source;
|
|
90
|
+
let low = 0;
|
|
91
|
+
let high = source.length;
|
|
92
|
+
while (low < high) {
|
|
93
|
+
const mid = Math.ceil((low + high) / 2);
|
|
94
|
+
if (escapeXml(source.slice(0, mid)).length <= maxEscapedLength) {
|
|
95
|
+
low = mid;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
high = mid - 1;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return source.slice(0, low).trimEnd();
|
|
102
|
+
};
|
|
103
|
+
export const renderXmlListSection = (tag, itemTag, values, options = {}) => {
|
|
104
|
+
const { itemCharLimit, remaining, includeEmpty = false } = options;
|
|
105
|
+
const open = `<${tag}>`;
|
|
106
|
+
const close = `</${tag}>`;
|
|
107
|
+
if (remaining !== undefined && open.length + close.length > remaining) {
|
|
108
|
+
return "";
|
|
109
|
+
}
|
|
110
|
+
let body = "";
|
|
111
|
+
for (const value of values) {
|
|
112
|
+
const normalized = value.trim();
|
|
113
|
+
if (!normalized)
|
|
114
|
+
continue;
|
|
115
|
+
const limited = itemCharLimit
|
|
116
|
+
? normalized.slice(0, itemCharLimit)
|
|
117
|
+
: normalized;
|
|
118
|
+
const itemOpen = `<${itemTag}>`;
|
|
119
|
+
const itemClose = `</${itemTag}>`;
|
|
120
|
+
const content = remaining === undefined ? limited : fitEscapedText(limited, remaining - open.length - close.length - body.length - itemOpen.length -
|
|
121
|
+
itemClose.length);
|
|
122
|
+
if (!content)
|
|
123
|
+
break;
|
|
124
|
+
body += `${itemOpen}${escapeXml(content)}</${itemTag}>`;
|
|
125
|
+
}
|
|
126
|
+
if (!body)
|
|
127
|
+
return includeEmpty ? `${open}${close}` : "";
|
|
128
|
+
return `${open}${body}${close}`;
|
|
129
|
+
};
|
|
130
|
+
export const renderXmlSingleSection = (tag, itemTag, value, options = {}) => {
|
|
131
|
+
if (!value)
|
|
132
|
+
return "";
|
|
133
|
+
const { valueCharLimit, remaining } = options;
|
|
134
|
+
const normalized = value.trim();
|
|
135
|
+
if (!normalized)
|
|
136
|
+
return "";
|
|
137
|
+
const limited = valueCharLimit
|
|
138
|
+
? normalized.slice(0, valueCharLimit)
|
|
139
|
+
: normalized;
|
|
140
|
+
const open = `<${tag}><${itemTag}>`;
|
|
141
|
+
const close = `</${itemTag}></${tag}>`;
|
|
142
|
+
const content = remaining === undefined
|
|
143
|
+
? limited
|
|
144
|
+
: fitEscapedText(limited, remaining - open.length - close.length);
|
|
145
|
+
if (!content)
|
|
146
|
+
return "";
|
|
147
|
+
const section = `${open}${escapeXml(content)}${close}`;
|
|
148
|
+
return remaining === undefined || section.length <= remaining ? section : "";
|
|
149
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type RuntimeTeardownTask = {
|
|
2
|
+
name: string;
|
|
3
|
+
run: () => void | Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
export interface RuntimeTeardownRegistration {
|
|
6
|
+
run(): Promise<void>;
|
|
7
|
+
dispose(): void;
|
|
8
|
+
}
|
|
9
|
+
type ShutdownRegistrationAdapter = {
|
|
10
|
+
addEventListener?: (type: string, listener: (event?: Event) => void, options?: boolean | {
|
|
11
|
+
once?: boolean;
|
|
12
|
+
capture?: boolean;
|
|
13
|
+
}) => void;
|
|
14
|
+
removeEventListener?: (type: string, listener: (event?: Event) => void, options?: boolean | EventListenerOptions) => void;
|
|
15
|
+
Deno?: {
|
|
16
|
+
addSignalListener?: (signal: "SIGINT" | "SIGTERM", handler: () => void) => void;
|
|
17
|
+
removeSignalListener?: (signal: "SIGINT" | "SIGTERM", handler: () => void) => void;
|
|
18
|
+
exit?: (code?: number) => never;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export declare function registerRuntimeTeardown(tasks: RuntimeTeardownTask[], runtime?: ShutdownRegistrationAdapter): RuntimeTeardownRegistration;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=runtime-teardown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-teardown.d.ts","sourceRoot":"","sources":["../../../src/src/services/runtime-teardown.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC,CAAC;AAEF,MAAM,WAAW,2BAA2B;IAC1C,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,KAAK,2BAA2B,GAAG;IACjC,gBAAgB,CAAC,EAAE,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,KACtD,IAAI,CAAC;IACV,mBAAmB,CAAC,EAAE,CACpB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,EACjC,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,KACrC,IAAI,CAAC;IACV,IAAI,CAAC,EAAE;QACL,iBAAiB,CAAC,EAAE,CAClB,MAAM,EAAE,QAAQ,GAAG,SAAS,EAC5B,OAAO,EAAE,MAAM,IAAI,KAChB,IAAI,CAAC;QACV,oBAAoB,CAAC,EAAE,CACrB,MAAM,EAAE,QAAQ,GAAG,SAAS,EAC5B,OAAO,EAAE,MAAM,IAAI,KAChB,IAAI,CAAC;QACV,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,KAAK,CAAC;KACjC,CAAC;CACH,CAAC;AAwBF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,mBAAmB,EAAE,EAC5B,OAAO,GAAE,2BAAmD,GAC3D,2BAA2B,CAuH7B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
const SHUTDOWN_EVENTS = ["unload", "beforeunload"];
|
|
4
|
+
const SHUTDOWN_SIGNALS = ["SIGINT", "SIGTERM"];
|
|
5
|
+
const SHUTDOWN_EXIT_CODE = {
|
|
6
|
+
SIGINT: 130,
|
|
7
|
+
SIGTERM: 143,
|
|
8
|
+
};
|
|
9
|
+
const activeRegistrations = new WeakMap();
|
|
10
|
+
const getShutdownNotice = (signal) => signal === "SIGINT"
|
|
11
|
+
? "Graceful shutdown in progress; waiting for pending memory flush. Press Ctrl+C again to exit immediately and drop pending memories."
|
|
12
|
+
: "Graceful shutdown in progress; waiting for pending memory flush. Send the signal again to exit immediately and drop pending memories.";
|
|
13
|
+
const getForcedShutdownNotice = (signal) => signal === "SIGINT"
|
|
14
|
+
? "Forced shutdown requested; exiting immediately and dropping pending memories."
|
|
15
|
+
: "Forced shutdown requested; exiting immediately after repeated shutdown signal and dropping pending memories.";
|
|
16
|
+
export function registerRuntimeTeardown(tasks, runtime = dntShim.dntGlobalThis) {
|
|
17
|
+
const runtimeKey = runtime;
|
|
18
|
+
let teardownPromise = null;
|
|
19
|
+
let eventListenersDisposed = false;
|
|
20
|
+
let signalListenersDisposed = false;
|
|
21
|
+
let registrationReleased = false;
|
|
22
|
+
let shutdownSignal = null;
|
|
23
|
+
let exitRequested = false;
|
|
24
|
+
const eventListeners = [];
|
|
25
|
+
const signalListeners = [];
|
|
26
|
+
const disposeEventListeners = () => {
|
|
27
|
+
if (eventListenersDisposed)
|
|
28
|
+
return;
|
|
29
|
+
eventListenersDisposed = true;
|
|
30
|
+
for (const { type, listener } of eventListeners) {
|
|
31
|
+
runtime.removeEventListener?.(type, listener, false);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const disposeSignalListeners = () => {
|
|
35
|
+
if (signalListenersDisposed)
|
|
36
|
+
return;
|
|
37
|
+
signalListenersDisposed = true;
|
|
38
|
+
for (const { signal, handler } of signalListeners) {
|
|
39
|
+
runtime.Deno?.removeSignalListener?.(signal, handler);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const releaseRegistration = () => {
|
|
43
|
+
if (registrationReleased)
|
|
44
|
+
return;
|
|
45
|
+
registrationReleased = true;
|
|
46
|
+
if (activeRegistrations.get(runtimeKey) === dispose) {
|
|
47
|
+
activeRegistrations.delete(runtimeKey);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const dispose = () => {
|
|
51
|
+
disposeEventListeners();
|
|
52
|
+
disposeSignalListeners();
|
|
53
|
+
releaseRegistration();
|
|
54
|
+
};
|
|
55
|
+
const requestExit = (signal) => {
|
|
56
|
+
if (exitRequested)
|
|
57
|
+
return;
|
|
58
|
+
exitRequested = true;
|
|
59
|
+
dispose();
|
|
60
|
+
runtime.Deno?.exit?.(SHUTDOWN_EXIT_CODE[signal]);
|
|
61
|
+
};
|
|
62
|
+
const run = (options) => {
|
|
63
|
+
if (teardownPromise)
|
|
64
|
+
return teardownPromise;
|
|
65
|
+
teardownPromise = (async () => {
|
|
66
|
+
disposeEventListeners();
|
|
67
|
+
if (!options?.keepSignalListeners) {
|
|
68
|
+
disposeSignalListeners();
|
|
69
|
+
}
|
|
70
|
+
releaseRegistration();
|
|
71
|
+
try {
|
|
72
|
+
for (const task of tasks) {
|
|
73
|
+
try {
|
|
74
|
+
await task.run();
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
logger.warn("Runtime teardown failed", {
|
|
78
|
+
resource: task.name,
|
|
79
|
+
err,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
disposeSignalListeners();
|
|
86
|
+
}
|
|
87
|
+
})();
|
|
88
|
+
return teardownPromise;
|
|
89
|
+
};
|
|
90
|
+
activeRegistrations.get(runtimeKey)?.();
|
|
91
|
+
for (const eventType of SHUTDOWN_EVENTS) {
|
|
92
|
+
const listener = () => {
|
|
93
|
+
void run();
|
|
94
|
+
};
|
|
95
|
+
runtime.addEventListener?.(eventType, listener, { once: true });
|
|
96
|
+
eventListeners.push({ type: eventType, listener });
|
|
97
|
+
}
|
|
98
|
+
for (const signal of SHUTDOWN_SIGNALS) {
|
|
99
|
+
const handler = () => {
|
|
100
|
+
if (shutdownSignal) {
|
|
101
|
+
logger.warn(getForcedShutdownNotice(signal), {
|
|
102
|
+
signal,
|
|
103
|
+
initialSignal: shutdownSignal,
|
|
104
|
+
});
|
|
105
|
+
requestExit(signal);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
shutdownSignal = signal;
|
|
109
|
+
logger.warn(getShutdownNotice(signal), { signal });
|
|
110
|
+
void run({ keepSignalListeners: true }).finally(() => {
|
|
111
|
+
requestExit(signal);
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
runtime.Deno?.addSignalListener?.(signal, handler);
|
|
115
|
+
signalListeners.push({ signal, handler });
|
|
116
|
+
}
|
|
117
|
+
activeRegistrations.set(runtimeKey, dispose);
|
|
118
|
+
return { run, dispose };
|
|
119
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Part } from "@opencode-ai/sdk";
|
|
2
|
+
import type { GraphitiEpisode } from "../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Narrow type for a single SDK message entry as returned by
|
|
5
|
+
* `session.messages()`.
|
|
6
|
+
*/
|
|
7
|
+
export type SdkMessage = {
|
|
8
|
+
info: {
|
|
9
|
+
role?: string;
|
|
10
|
+
id?: string;
|
|
11
|
+
};
|
|
12
|
+
parts: Part[];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Normalize an SDK response that may be wrapped in `{ data: … }` or returned
|
|
16
|
+
* directly. Returns the inner value cast to `T`, or `undefined` when the
|
|
17
|
+
* response is absent.
|
|
18
|
+
*
|
|
19
|
+
* This replaces the repeated `"data" in response ? (response as
|
|
20
|
+
* { data?: … }).data : response` pattern found in session.ts and
|
|
21
|
+
* context-limit.ts.
|
|
22
|
+
*/
|
|
23
|
+
export declare function unwrapSdkResponse<T>(response: unknown): T | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Extract the messages array from a raw `session.messages()` response.
|
|
26
|
+
* Returns an empty array when the response is missing or malformed.
|
|
27
|
+
*/
|
|
28
|
+
export declare function extractSdkMessages(response: unknown): SdkMessage[];
|
|
29
|
+
/**
|
|
30
|
+
* Extract the provider list from a raw `provider.list()` response.
|
|
31
|
+
* Returns an empty array when the response is missing or malformed.
|
|
32
|
+
*/
|
|
33
|
+
export type SdkProvider = {
|
|
34
|
+
id?: string;
|
|
35
|
+
models?: SdkModel[];
|
|
36
|
+
};
|
|
37
|
+
export type SdkModel = {
|
|
38
|
+
id?: string;
|
|
39
|
+
limit?: {
|
|
40
|
+
context?: number;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export declare function extractSdkProviders(response: unknown): SdkProvider[];
|
|
44
|
+
/**
|
|
45
|
+
* Normalize a raw Graphiti episode object so that `sourceDescription` is
|
|
46
|
+
* always the canonical field regardless of whether the payload used
|
|
47
|
+
* camelCase (`sourceDescription`) or snake_case (`source_description`).
|
|
48
|
+
*
|
|
49
|
+
* Call this at the API boundary (e.g. inside `GraphitiClient.getEpisodes`)
|
|
50
|
+
* so all downstream consumers only need to read `episode.sourceDescription`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function normalizeEpisode(raw: GraphitiEpisode & {
|
|
53
|
+
source_description?: string;
|
|
54
|
+
}): GraphitiEpisode;
|
|
55
|
+
//# sourceMappingURL=sdk-normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-normalize.d.ts","sourceRoot":"","sources":["../../../src/src/services/sdk-normalize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAA4B,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,KAAK,EAAE,IAAI,EAAE,CAAC;CACf,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,CAAC,GAAG,SAAS,CAMrE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,OAAO,GAChB,UAAU,EAAE,CAGd;AAED;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9B,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,OAAO,GAAG,WAAW,EAAE,CAmBpE;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,eAAe,GAAG;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,GACA,eAAe,CAMjB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize an SDK response that may be wrapped in `{ data: … }` or returned
|
|
3
|
+
* directly. Returns the inner value cast to `T`, or `undefined` when the
|
|
4
|
+
* response is absent.
|
|
5
|
+
*
|
|
6
|
+
* This replaces the repeated `"data" in response ? (response as
|
|
7
|
+
* { data?: … }).data : response` pattern found in session.ts and
|
|
8
|
+
* context-limit.ts.
|
|
9
|
+
*/
|
|
10
|
+
export function unwrapSdkResponse(response) {
|
|
11
|
+
if (response == null)
|
|
12
|
+
return undefined;
|
|
13
|
+
if (typeof response === "object" && "data" in response) {
|
|
14
|
+
return response.data;
|
|
15
|
+
}
|
|
16
|
+
return response;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Extract the messages array from a raw `session.messages()` response.
|
|
20
|
+
* Returns an empty array when the response is missing or malformed.
|
|
21
|
+
*/
|
|
22
|
+
export function extractSdkMessages(response) {
|
|
23
|
+
const payload = unwrapSdkResponse(response);
|
|
24
|
+
return Array.isArray(payload) ? payload : [];
|
|
25
|
+
}
|
|
26
|
+
export function extractSdkProviders(response) {
|
|
27
|
+
// provider.list() may return `{ providers: [...] }` directly (no data wrap).
|
|
28
|
+
if (response != null && typeof response === "object") {
|
|
29
|
+
const obj = response;
|
|
30
|
+
if (Array.isArray(obj["providers"])) {
|
|
31
|
+
return obj["providers"];
|
|
32
|
+
}
|
|
33
|
+
if ("data" in obj) {
|
|
34
|
+
const data = obj["data"];
|
|
35
|
+
if (data != null && typeof data === "object") {
|
|
36
|
+
const dataObj = data;
|
|
37
|
+
if (Array.isArray(dataObj["providers"])) {
|
|
38
|
+
return dataObj["providers"];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (Array.isArray(data))
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Normalize a raw Graphiti episode object so that `sourceDescription` is
|
|
49
|
+
* always the canonical field regardless of whether the payload used
|
|
50
|
+
* camelCase (`sourceDescription`) or snake_case (`source_description`).
|
|
51
|
+
*
|
|
52
|
+
* Call this at the API boundary (e.g. inside `GraphitiClient.getEpisodes`)
|
|
53
|
+
* so all downstream consumers only need to read `episode.sourceDescription`.
|
|
54
|
+
*/
|
|
55
|
+
export function normalizeEpisode(raw) {
|
|
56
|
+
const { source_description, ...rest } = raw;
|
|
57
|
+
return {
|
|
58
|
+
...rest,
|
|
59
|
+
sourceDescription: rest.sourceDescription ?? source_description,
|
|
60
|
+
};
|
|
61
|
+
}
|