opencode-graphiti 0.1.9 → 0.1.10
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 +7 -1
- package/esm/_dnt.polyfills.d.ts +50 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +37 -0
- package/esm/mod.d.ts +1 -0
- package/esm/mod.d.ts.map +1 -1
- package/esm/mod.js +1 -0
- package/esm/src/config.d.ts +7 -1
- package/esm/src/config.d.ts.map +1 -1
- package/esm/src/config.js +17 -5
- package/esm/src/handlers/chat.d.ts.map +1 -1
- package/esm/src/handlers/chat.js +51 -42
- package/esm/src/handlers/event.d.ts +1 -1
- package/esm/src/handlers/event.d.ts.map +1 -1
- package/esm/src/handlers/event.js +42 -46
- package/esm/src/handlers/messages.d.ts.map +1 -1
- package/esm/src/handlers/messages.js +2 -3
- package/esm/src/index.js +2 -2
- package/esm/src/services/client.d.ts +7 -0
- package/esm/src/services/client.d.ts.map +1 -1
- package/esm/src/services/client.js +22 -24
- package/esm/src/services/compaction.d.ts.map +1 -1
- package/esm/src/services/compaction.js +24 -33
- 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 +1 -1
- package/esm/src/services/context-limit.d.ts.map +1 -1
- package/esm/src/services/context-limit.js +12 -14
- package/esm/src/services/context.d.ts +27 -7
- package/esm/src/services/context.d.ts.map +1 -1
- package/esm/src/services/context.js +34 -2
- package/esm/src/services/logger.js +2 -4
- 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 +4 -2
- package/esm/src/session.d.ts.map +1 -1
- package/esm/src/session.js +38 -34
- package/esm/src/types/index.d.ts +13 -14
- package/esm/src/types/index.d.ts.map +1 -1
- package/esm/src/utils.d.ts +6 -0
- package/esm/src/utils.d.ts.map +1 -1
- package/esm/src/utils.js +16 -2
- package/package.json +1 -1
- package/script/_dnt.polyfills.d.ts +50 -0
- package/script/_dnt.polyfills.d.ts.map +1 -0
- package/script/_dnt.polyfills.js +38 -0
- package/script/mod.d.ts +1 -0
- package/script/mod.d.ts.map +1 -1
- package/script/mod.js +1 -0
- package/script/src/config.d.ts +7 -1
- package/script/src/config.d.ts.map +1 -1
- package/script/src/config.js +20 -5
- package/script/src/handlers/chat.d.ts.map +1 -1
- package/script/src/handlers/chat.js +49 -40
- package/script/src/handlers/event.d.ts +1 -1
- package/script/src/handlers/event.d.ts.map +1 -1
- package/script/src/handlers/event.js +41 -45
- package/script/src/handlers/messages.d.ts.map +1 -1
- package/script/src/handlers/messages.js +2 -3
- package/script/src/index.js +2 -2
- package/script/src/services/client.d.ts +7 -0
- package/script/src/services/client.d.ts.map +1 -1
- package/script/src/services/client.js +22 -24
- package/script/src/services/compaction.d.ts.map +1 -1
- package/script/src/services/compaction.js +24 -33
- 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 +1 -1
- package/script/src/services/context-limit.d.ts.map +1 -1
- package/script/src/services/context-limit.js +13 -15
- package/script/src/services/context.d.ts +27 -7
- package/script/src/services/context.d.ts.map +1 -1
- package/script/src/services/context.js +36 -4
- package/script/src/services/logger.js +2 -4
- 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 +4 -2
- package/script/src/session.d.ts.map +1 -1
- package/script/src/session.js +38 -34
- package/script/src/types/index.d.ts +13 -14
- package/script/src/types/index.d.ts.map +1 -1
- package/script/src/utils.d.ts +6 -0
- package/script/src/utils.d.ts.map +1 -1
- package/script/src/utils.js +18 -3
|
@@ -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,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.unwrapSdkResponse = unwrapSdkResponse;
|
|
4
|
+
exports.extractSdkMessages = extractSdkMessages;
|
|
5
|
+
exports.extractSdkProviders = extractSdkProviders;
|
|
6
|
+
exports.normalizeEpisode = normalizeEpisode;
|
|
7
|
+
/**
|
|
8
|
+
* Normalize an SDK response that may be wrapped in `{ data: … }` or returned
|
|
9
|
+
* directly. Returns the inner value cast to `T`, or `undefined` when the
|
|
10
|
+
* response is absent.
|
|
11
|
+
*
|
|
12
|
+
* This replaces the repeated `"data" in response ? (response as
|
|
13
|
+
* { data?: … }).data : response` pattern found in session.ts and
|
|
14
|
+
* context-limit.ts.
|
|
15
|
+
*/
|
|
16
|
+
function unwrapSdkResponse(response) {
|
|
17
|
+
if (response == null)
|
|
18
|
+
return undefined;
|
|
19
|
+
if (typeof response === "object" && "data" in response) {
|
|
20
|
+
return response.data;
|
|
21
|
+
}
|
|
22
|
+
return response;
|
|
23
|
+
}
|
|
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
|
+
function extractSdkMessages(response) {
|
|
29
|
+
const payload = unwrapSdkResponse(response);
|
|
30
|
+
return Array.isArray(payload) ? payload : [];
|
|
31
|
+
}
|
|
32
|
+
function extractSdkProviders(response) {
|
|
33
|
+
// provider.list() may return `{ providers: [...] }` directly (no data wrap).
|
|
34
|
+
if (response != null && typeof response === "object") {
|
|
35
|
+
const obj = response;
|
|
36
|
+
if (Array.isArray(obj["providers"])) {
|
|
37
|
+
return obj["providers"];
|
|
38
|
+
}
|
|
39
|
+
if ("data" in obj) {
|
|
40
|
+
const data = obj["data"];
|
|
41
|
+
if (data != null && typeof data === "object") {
|
|
42
|
+
const dataObj = data;
|
|
43
|
+
if (Array.isArray(dataObj["providers"])) {
|
|
44
|
+
return dataObj["providers"];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (Array.isArray(data))
|
|
48
|
+
return data;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Normalize a raw Graphiti episode object so that `sourceDescription` is
|
|
55
|
+
* always the canonical field regardless of whether the payload used
|
|
56
|
+
* camelCase (`sourceDescription`) or snake_case (`source_description`).
|
|
57
|
+
*
|
|
58
|
+
* Call this at the API boundary (e.g. inside `GraphitiClient.getEpisodes`)
|
|
59
|
+
* so all downstream consumers only need to read `episode.sourceDescription`.
|
|
60
|
+
*/
|
|
61
|
+
function normalizeEpisode(raw) {
|
|
62
|
+
const { source_description, ...rest } = raw;
|
|
63
|
+
return {
|
|
64
|
+
...rest,
|
|
65
|
+
sourceDescription: rest.sourceDescription ?? source_description,
|
|
66
|
+
};
|
|
67
|
+
}
|
package/script/src/session.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export type SessionState = {
|
|
|
22
22
|
messageCount: number;
|
|
23
23
|
/** Buffered message strings awaiting flush. */
|
|
24
24
|
pendingMessages: string[];
|
|
25
|
+
/** Last successfully saved idle-session snapshot body. */
|
|
26
|
+
lastSnapshotBody?: string;
|
|
25
27
|
/** Context window limit in tokens. */
|
|
26
28
|
contextLimit: number;
|
|
27
29
|
/** True when this session is the primary (non-subagent) session. */
|
|
@@ -41,6 +43,8 @@ export declare class SessionManager {
|
|
|
41
43
|
private pendingAssistantMessages;
|
|
42
44
|
private bufferedAssistantMessageIds;
|
|
43
45
|
constructor(defaultGroupId: string, defaultUserGroupId: string, sdkClient: OpencodeClient, graphitiClient: GraphitiClient);
|
|
46
|
+
/** Create a default main-session state for the given group IDs. */
|
|
47
|
+
createDefaultState(groupId: string, userGroupId: string): SessionState;
|
|
44
48
|
/** Get the current session state, if present. */
|
|
45
49
|
getState(sessionId: string): SessionState | undefined;
|
|
46
50
|
/** Persist session state for the given session ID. */
|
|
@@ -54,8 +58,6 @@ export declare class SessionManager {
|
|
|
54
58
|
state: SessionState | null;
|
|
55
59
|
resolved: boolean;
|
|
56
60
|
}>;
|
|
57
|
-
/** Determine whether a session is a subagent session. */
|
|
58
|
-
isSubagentSession(sessionId: string): Promise<boolean>;
|
|
59
61
|
/** Buffer partial assistant text for a streaming message. */
|
|
60
62
|
bufferAssistantPart(sessionId: string, messageId: string, text: string): void;
|
|
61
63
|
/** Check if an assistant message has already been finalized. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAM3D;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,wDAAwD;IACxD,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,qEAAqE;IACrE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,qBAAa,cAAc;IAUvB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAZjC,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,aAAa,CAAoC;IACzD,OAAO,CAAC,wBAAwB,CAG5B;IACJ,OAAO,CAAC,2BAA2B,CAAqB;gBAGrC,cAAc,EAAE,MAAM,EACtB,kBAAkB,EAAE,MAAM,EAC1B,SAAS,EAAE,cAAc,EACzB,cAAc,EAAE,cAAc;IAGjD,mEAAmE;IACnE,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY;IAiBtE,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIrD,sDAAsD;IACtD,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI;IAItD,gDAAgD;IAChD,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAI7D,qDAAqD;IAC/C,eAAe,CACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAsBrC,yDAAyD;IACnD,mBAAmB,CACvB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAmB7D,6DAA6D;IAC7D,mBAAmB,CACjB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,IAAI;IAKP,gEAAgE;IAChE,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO;IAKlE;;OAEG;IACH,wBAAwB,CACtB,KAAK,EAAE,YAAY,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,IAAI;IAwCP,+EAA+E;IACzE,oBAAoB,CACxB,SAAS,EAAE,MAAM,EACjB,iBAAiB,EAAE,MAAM,EACzB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAgFhB,iDAAiD;IACjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAKlE,uCAAuC;IACvC,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;YAyBxB,2BAA2B;CAwB1C"}
|
package/script/src/session.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SessionManager = void 0;
|
|
4
|
+
const sdk_normalize_js_1 = require("./services/sdk-normalize.js");
|
|
5
|
+
const constants_js_1 = require("./services/constants.js");
|
|
4
6
|
const logger_js_1 = require("./services/logger.js");
|
|
5
7
|
const utils_js_1 = require("./utils.js");
|
|
6
8
|
/**
|
|
@@ -58,6 +60,23 @@ class SessionManager {
|
|
|
58
60
|
value: new Set()
|
|
59
61
|
});
|
|
60
62
|
}
|
|
63
|
+
/** Create a default main-session state for the given group IDs. */
|
|
64
|
+
createDefaultState(groupId, userGroupId) {
|
|
65
|
+
return {
|
|
66
|
+
groupId,
|
|
67
|
+
userGroupId,
|
|
68
|
+
injectedMemories: false,
|
|
69
|
+
lastInjectionFactUuids: [],
|
|
70
|
+
cachedMemoryContext: undefined,
|
|
71
|
+
cachedFactUuids: undefined,
|
|
72
|
+
visibleFactUuids: [],
|
|
73
|
+
messageCount: 0,
|
|
74
|
+
pendingMessages: [],
|
|
75
|
+
lastSnapshotBody: undefined,
|
|
76
|
+
contextLimit: constants_js_1.DEFAULT_CONTEXT_LIMIT,
|
|
77
|
+
isMain: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
61
80
|
/** Get the current session state, if present. */
|
|
62
81
|
getState(sessionId) {
|
|
63
82
|
return this.sessions.get(sessionId);
|
|
@@ -105,28 +124,11 @@ class SessionManager {
|
|
|
105
124
|
}
|
|
106
125
|
let state = this.sessions.get(sessionId);
|
|
107
126
|
if (!state) {
|
|
108
|
-
state =
|
|
109
|
-
groupId: this.defaultGroupId,
|
|
110
|
-
userGroupId: this.defaultUserGroupId,
|
|
111
|
-
injectedMemories: false,
|
|
112
|
-
lastInjectionFactUuids: [],
|
|
113
|
-
cachedMemoryContext: undefined,
|
|
114
|
-
cachedFactUuids: undefined,
|
|
115
|
-
visibleFactUuids: [],
|
|
116
|
-
messageCount: 0,
|
|
117
|
-
pendingMessages: [],
|
|
118
|
-
contextLimit: 200_000,
|
|
119
|
-
isMain: true,
|
|
120
|
-
};
|
|
127
|
+
state = this.createDefaultState(this.defaultGroupId, this.defaultUserGroupId);
|
|
121
128
|
this.sessions.set(sessionId, state);
|
|
122
129
|
}
|
|
123
130
|
return { state, resolved: true };
|
|
124
131
|
}
|
|
125
|
-
/** Determine whether a session is a subagent session. */
|
|
126
|
-
async isSubagentSession(sessionId) {
|
|
127
|
-
const parentId = await this.resolveParentId(sessionId);
|
|
128
|
-
return !!parentId;
|
|
129
|
-
}
|
|
130
132
|
/** Buffer partial assistant text for a streaming message. */
|
|
131
133
|
bufferAssistantPart(sessionId, messageId, text) {
|
|
132
134
|
const key = `${sessionId}:${messageId}`;
|
|
@@ -259,15 +261,24 @@ class SessionManager {
|
|
|
259
261
|
deleteSession(sessionId) {
|
|
260
262
|
this.sessions.delete(sessionId);
|
|
261
263
|
this.parentIdCache.delete(sessionId);
|
|
264
|
+
// Collect matching keys first, then delete in a second pass to avoid
|
|
265
|
+
// mutating a Map/Set while iterating over its live iterator.
|
|
266
|
+
const prefix = `${sessionId}:`;
|
|
267
|
+
const pendingToDelete = [];
|
|
262
268
|
for (const key of this.pendingAssistantMessages.keys()) {
|
|
263
|
-
if (key.startsWith(
|
|
264
|
-
|
|
265
|
-
|
|
269
|
+
if (key.startsWith(prefix))
|
|
270
|
+
pendingToDelete.push(key);
|
|
271
|
+
}
|
|
272
|
+
for (const key of pendingToDelete) {
|
|
273
|
+
this.pendingAssistantMessages.delete(key);
|
|
266
274
|
}
|
|
275
|
+
const bufferedToDelete = [];
|
|
267
276
|
for (const key of this.bufferedAssistantMessageIds) {
|
|
268
|
-
if (key.startsWith(
|
|
269
|
-
|
|
270
|
-
|
|
277
|
+
if (key.startsWith(prefix))
|
|
278
|
+
bufferedToDelete.push(key);
|
|
279
|
+
}
|
|
280
|
+
for (const key of bufferedToDelete) {
|
|
281
|
+
this.bufferedAssistantMessageIds.delete(key);
|
|
271
282
|
}
|
|
272
283
|
}
|
|
273
284
|
async fetchLatestAssistantMessage(sessionId) {
|
|
@@ -276,18 +287,11 @@ class SessionManager {
|
|
|
276
287
|
path: { id: sessionId },
|
|
277
288
|
query: { limit: 20 },
|
|
278
289
|
});
|
|
279
|
-
const
|
|
280
|
-
"data" in response
|
|
281
|
-
? response.data
|
|
282
|
-
: response;
|
|
283
|
-
const messages = Array.isArray(payload)
|
|
284
|
-
? payload
|
|
285
|
-
: [];
|
|
290
|
+
const messages = (0, sdk_normalize_js_1.extractSdkMessages)(response);
|
|
286
291
|
if (messages.length === 0)
|
|
287
292
|
return null;
|
|
288
|
-
const lastAssistant =
|
|
289
|
-
.
|
|
290
|
-
.find((message) => message.info?.role === "assistant");
|
|
293
|
+
const lastAssistant = messages
|
|
294
|
+
.findLast((message) => message.info?.role === "assistant");
|
|
291
295
|
if (!lastAssistant)
|
|
292
296
|
return null;
|
|
293
297
|
const text = (0, utils_js_1.extractTextFromParts)(lastAssistant.parts);
|
|
@@ -30,11 +30,6 @@ export interface GraphitiFact {
|
|
|
30
30
|
uuid: string;
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
-
/** Response payload containing Graphiti facts. */
|
|
34
|
-
export interface GraphitiFactsResponse {
|
|
35
|
-
/** List of facts from Graphiti. */
|
|
36
|
-
facts: GraphitiFact[];
|
|
37
|
-
}
|
|
38
33
|
/** A node retrieved from the Graphiti knowledge graph. */
|
|
39
34
|
export interface GraphitiNode {
|
|
40
35
|
/** Unique identifier for the node. */
|
|
@@ -46,12 +41,15 @@ export interface GraphitiNode {
|
|
|
46
41
|
/** Optional labels associated with the node. */
|
|
47
42
|
labels?: string[];
|
|
48
43
|
}
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
/**
|
|
45
|
+
* An episode retrieved from Graphiti memory.
|
|
46
|
+
*
|
|
47
|
+
* `sourceDescription` is the canonical field. Raw payloads may carry either
|
|
48
|
+
* `sourceDescription` (camelCase) or `source_description` (snake_case); the
|
|
49
|
+
* boundary helper `normalizeEpisode()` in `src/services/sdk-normalize.ts`
|
|
50
|
+
* collapses both into `sourceDescription` so downstream consumers only need to
|
|
51
|
+
* check one field.
|
|
52
|
+
*/
|
|
55
53
|
export interface GraphitiEpisode {
|
|
56
54
|
/** Unique identifier for the episode. */
|
|
57
55
|
uuid: string;
|
|
@@ -61,10 +59,11 @@ export interface GraphitiEpisode {
|
|
|
61
59
|
content: string;
|
|
62
60
|
/** Optional episode source type. */
|
|
63
61
|
source?: string;
|
|
64
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Canonical source description (normalized from either camelCase or
|
|
64
|
+
* snake_case payload). Always populated by `normalizeEpisode()`.
|
|
65
|
+
*/
|
|
65
66
|
sourceDescription?: string;
|
|
66
|
-
/** Optional source description (snake_case payload). */
|
|
67
|
-
source_description?: string;
|
|
68
67
|
/** Optional episode creation timestamp. */
|
|
69
68
|
created_at?: string;
|
|
70
69
|
/** Optional labels associated with the episode. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/types/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,cAAc,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/types/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,aAAa,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,cAAc,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,uCAAuC;IACvC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB"}
|
package/script/src/utils.d.ts
CHANGED
|
@@ -18,4 +18,10 @@ export declare const isTextPart: (value: unknown) => value is Part & {
|
|
|
18
18
|
* Extract and join text from OpenCode message parts.
|
|
19
19
|
*/
|
|
20
20
|
export declare const extractTextFromParts: (parts: Part[]) => string;
|
|
21
|
+
/**
|
|
22
|
+
* Truncate `text` to at most `budget` characters without cutting mid-line.
|
|
23
|
+
* Prefers to break at the last newline within the budget window; falls back
|
|
24
|
+
* to a raw slice only when the candidate contains no newline.
|
|
25
|
+
*/
|
|
26
|
+
export declare const truncateAtLineBoundary: (text: string, budget: number) => string;
|
|
21
27
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAW7C;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,SAAS,MAAM,EACf,kBAAyB,KACxB,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAW7C;;GAEG;AACH,eAAO,MAAM,WAAW,GACtB,SAAS,MAAM,EACf,kBAAyB,KACxB,MAKF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,MAAM,EACf,kBAAyB,KACxB,MAMF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,IAAI,GAAG;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAMd,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,IAAI,EAAE,KAAG,MACe,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,MAAM,EACZ,QAAQ,MAAM,KACb,MAKF,CAAC"}
|
package/script/src/utils.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.extractTextFromParts = exports.isTextPart = exports.makeUserGroupId = exports.makeGroupId = void 0;
|
|
6
|
+
exports.truncateAtLineBoundary = exports.extractTextFromParts = exports.isTextPart = exports.makeUserGroupId = exports.makeGroupId = void 0;
|
|
7
7
|
const node_os_1 = __importDefault(require("node:os"));
|
|
8
8
|
const node_process_1 = __importDefault(require("node:process"));
|
|
9
9
|
const getProjectName = (directory) => directory.split("/").filter(Boolean).at(-1)?.trim() || "default";
|
|
@@ -13,7 +13,8 @@ const getUserName = (home = node_os_1.default.homedir().split("/").filter(Boolea
|
|
|
13
13
|
*/
|
|
14
14
|
const makeGroupId = (prefix, directory = node_process_1.default.cwd()) => {
|
|
15
15
|
const projectName = getProjectName(directory);
|
|
16
|
-
const
|
|
16
|
+
const prefixPart = prefix ? `${prefix}-` : "";
|
|
17
|
+
const rawGroupId = `${prefixPart}${projectName}__main`;
|
|
17
18
|
return rawGroupId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
18
19
|
};
|
|
19
20
|
exports.makeGroupId = makeGroupId;
|
|
@@ -23,7 +24,8 @@ exports.makeGroupId = makeGroupId;
|
|
|
23
24
|
const makeUserGroupId = (prefix, directory = node_process_1.default.cwd()) => {
|
|
24
25
|
const projectName = getProjectName(directory);
|
|
25
26
|
const userName = getUserName();
|
|
26
|
-
const
|
|
27
|
+
const prefixPart = prefix ? `${prefix}-` : "";
|
|
28
|
+
const rawGroupId = `${prefixPart}${projectName}__user-${userName}`;
|
|
27
29
|
return rawGroupId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
28
30
|
};
|
|
29
31
|
exports.makeUserGroupId = makeUserGroupId;
|
|
@@ -43,3 +45,16 @@ exports.isTextPart = isTextPart;
|
|
|
43
45
|
*/
|
|
44
46
|
const extractTextFromParts = (parts) => parts.filter(exports.isTextPart).map((part) => part.text).join(" ").trim();
|
|
45
47
|
exports.extractTextFromParts = extractTextFromParts;
|
|
48
|
+
/**
|
|
49
|
+
* Truncate `text` to at most `budget` characters without cutting mid-line.
|
|
50
|
+
* Prefers to break at the last newline within the budget window; falls back
|
|
51
|
+
* to a raw slice only when the candidate contains no newline.
|
|
52
|
+
*/
|
|
53
|
+
const truncateAtLineBoundary = (text, budget) => {
|
|
54
|
+
if (text.length <= budget)
|
|
55
|
+
return text;
|
|
56
|
+
const candidate = text.slice(0, budget);
|
|
57
|
+
const lastNl = candidate.lastIndexOf("\n");
|
|
58
|
+
return lastNl > 0 ? candidate.slice(0, lastNl) : candidate;
|
|
59
|
+
};
|
|
60
|
+
exports.truncateAtLineBoundary = truncateAtLineBoundary;
|