dsh-tdai-memory 0.3.1 → 0.3.2
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/client.js +4 -3
- package/index.js +436 -436
- package/package.json +1 -1
- package/vendor/tdai/adapters/standalone/llm-runner.js +274 -274
- package/vendor/tdai/config.js +366 -366
- package/vendor/tdai/core/hooks/auto-recall.js +13 -13
- package/vendor/tdai/core/prompts/l1-dedup.js +64 -64
- package/vendor/tdai/core/prompts/l1-extraction.js +98 -98
- package/vendor/tdai/core/prompts/persona-generation.js +125 -125
- package/vendor/tdai/core/prompts/scene-extraction.js +224 -224
- package/vendor/tdai/core/scene/scene-navigation.js +3 -3
- package/vendor/tdai/core/seed/seed-runtime.js +318 -318
- package/vendor/tdai/core/store/sqlite.js +190 -190
- package/vendor/tdai/core/tdai-core.js +450 -450
- package/vendor/tdai/utils/session-header-fetch.js +88 -88
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Fetch wrapper that injects a stable session-id header (`x-opencode-session`)
|
|
3
|
-
* into outgoing LLM requests.
|
|
4
|
-
*
|
|
5
|
-
* OpenCode Go (and other OpenAI-compatible gateways) require every request to
|
|
6
|
-
* carry a stable per-conversation id; requests without it started erroring
|
|
7
|
-
* after 2026-09-06. The value is:
|
|
8
|
-
*
|
|
9
|
-
* 1. An explicit configured `sessionId`, when set;
|
|
10
|
-
* 2. Otherwise a persistent per-instance random id. The id is generated once
|
|
11
|
-
* and stored under the TDAI data dir (`<dataDir>/session-id`), so it
|
|
12
|
-
* survives restarts — one stable id per plugin instance, which is exactly
|
|
13
|
-
* what the gateway asks for when the client has no real conversation.
|
|
14
|
-
*
|
|
15
|
-
* Embedding and other non-chat traffic still gets the header (harmless, and
|
|
16
|
-
* gateways may require it on every request). When disabled, returns
|
|
17
|
-
* `globalThis.fetch` unchanged.
|
|
18
|
-
*/
|
|
19
|
-
import { randomUUID } from "node:crypto";
|
|
20
|
-
import { join } from "node:path";
|
|
21
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
22
|
-
|
|
23
|
-
const SESSION_ID_FILE = "session-id";
|
|
24
|
-
|
|
25
|
-
let cachedId = "";
|
|
26
|
-
/** Load-or-create a persistent per-instance session id under `dataDir`. */
|
|
27
|
-
export async function resolvePersistentSessionId(dataDir) {
|
|
28
|
-
if (cachedId)
|
|
29
|
-
return cachedId;
|
|
30
|
-
if (!dataDir) {
|
|
31
|
-
cachedId = `tdai-memory-${randomUUID()}`;
|
|
32
|
-
return cachedId;
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
const file = join(dataDir, SESSION_ID_FILE);
|
|
36
|
-
const existing = await readFile(file, "utf8").catch(() => "");
|
|
37
|
-
const trimmed = existing.trim();
|
|
38
|
-
if (trimmed) {
|
|
39
|
-
cachedId = trimmed;
|
|
40
|
-
return cachedId;
|
|
41
|
-
}
|
|
42
|
-
const fresh = `tdai-memory-${randomUUID()}`;
|
|
43
|
-
await mkdir(dataDir, { recursive: true });
|
|
44
|
-
await writeFile(file, fresh, "utf8");
|
|
45
|
-
cachedId = fresh;
|
|
46
|
-
return cachedId;
|
|
47
|
-
}
|
|
48
|
-
catch {
|
|
49
|
-
// Any persistence failure degrades to a per-process id.
|
|
50
|
-
cachedId = `tdai-memory-${randomUUID()}`;
|
|
51
|
-
return cachedId;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Build a session-id header value for a request.
|
|
57
|
-
* @param {object} opts { send, headerName, sessionId, persistentId }
|
|
58
|
-
* @returns {Record<string,string>|undefined} header object, or undefined when disabled.
|
|
59
|
-
*/
|
|
60
|
-
export function sessionHeaderOf({ send, headerName, sessionId, persistentId }) {
|
|
61
|
-
if (send === false)
|
|
62
|
-
return undefined;
|
|
63
|
-
const id = (sessionId && String(sessionId).trim()) || persistentId || "";
|
|
64
|
-
if (!id)
|
|
65
|
-
return undefined;
|
|
66
|
-
return { [headerName || "x-opencode-session"]: id };
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Create a fetch wrapper that injects the session-id header into every request.
|
|
71
|
-
* @param {object} opts { send, headerName, sessionId, persistentId }
|
|
72
|
-
* @returns {typeof globalThis.fetch}
|
|
73
|
-
*/
|
|
74
|
-
export function createSessionHeaderFetch({ send, headerName, sessionId, persistentId }) {
|
|
75
|
-
if (send === false)
|
|
76
|
-
return globalThis.fetch;
|
|
77
|
-
const header = sessionHeaderOf({ send, headerName, sessionId, persistentId });
|
|
78
|
-
if (!header)
|
|
79
|
-
return globalThis.fetch;
|
|
80
|
-
return (async (input, init) => {
|
|
81
|
-
const next = init ? { ...init } : {};
|
|
82
|
-
next.headers = new Headers(init?.headers);
|
|
83
|
-
for (const [k, v] of Object.entries(header)) {
|
|
84
|
-
next.headers.set(k, v);
|
|
85
|
-
}
|
|
86
|
-
return globalThis.fetch(input, next);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Fetch wrapper that injects a stable session-id header (`x-opencode-session`)
|
|
3
|
+
* into outgoing LLM requests.
|
|
4
|
+
*
|
|
5
|
+
* OpenCode Go (and other OpenAI-compatible gateways) require every request to
|
|
6
|
+
* carry a stable per-conversation id; requests without it started erroring
|
|
7
|
+
* after 2026-09-06. The value is:
|
|
8
|
+
*
|
|
9
|
+
* 1. An explicit configured `sessionId`, when set;
|
|
10
|
+
* 2. Otherwise a persistent per-instance random id. The id is generated once
|
|
11
|
+
* and stored under the TDAI data dir (`<dataDir>/session-id`), so it
|
|
12
|
+
* survives restarts — one stable id per plugin instance, which is exactly
|
|
13
|
+
* what the gateway asks for when the client has no real conversation.
|
|
14
|
+
*
|
|
15
|
+
* Embedding and other non-chat traffic still gets the header (harmless, and
|
|
16
|
+
* gateways may require it on every request). When disabled, returns
|
|
17
|
+
* `globalThis.fetch` unchanged.
|
|
18
|
+
*/
|
|
19
|
+
import { randomUUID } from "node:crypto";
|
|
20
|
+
import { join } from "node:path";
|
|
21
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
22
|
+
|
|
23
|
+
const SESSION_ID_FILE = "session-id";
|
|
24
|
+
|
|
25
|
+
let cachedId = "";
|
|
26
|
+
/** Load-or-create a persistent per-instance session id under `dataDir`. */
|
|
27
|
+
export async function resolvePersistentSessionId(dataDir) {
|
|
28
|
+
if (cachedId)
|
|
29
|
+
return cachedId;
|
|
30
|
+
if (!dataDir) {
|
|
31
|
+
cachedId = `tdai-memory-${randomUUID()}`;
|
|
32
|
+
return cachedId;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const file = join(dataDir, SESSION_ID_FILE);
|
|
36
|
+
const existing = await readFile(file, "utf8").catch(() => "");
|
|
37
|
+
const trimmed = existing.trim();
|
|
38
|
+
if (trimmed) {
|
|
39
|
+
cachedId = trimmed;
|
|
40
|
+
return cachedId;
|
|
41
|
+
}
|
|
42
|
+
const fresh = `tdai-memory-${randomUUID()}`;
|
|
43
|
+
await mkdir(dataDir, { recursive: true });
|
|
44
|
+
await writeFile(file, fresh, "utf8");
|
|
45
|
+
cachedId = fresh;
|
|
46
|
+
return cachedId;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Any persistence failure degrades to a per-process id.
|
|
50
|
+
cachedId = `tdai-memory-${randomUUID()}`;
|
|
51
|
+
return cachedId;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Build a session-id header value for a request.
|
|
57
|
+
* @param {object} opts { send, headerName, sessionId, persistentId }
|
|
58
|
+
* @returns {Record<string,string>|undefined} header object, or undefined when disabled.
|
|
59
|
+
*/
|
|
60
|
+
export function sessionHeaderOf({ send, headerName, sessionId, persistentId }) {
|
|
61
|
+
if (send === false)
|
|
62
|
+
return undefined;
|
|
63
|
+
const id = (sessionId && String(sessionId).trim()) || persistentId || "";
|
|
64
|
+
if (!id)
|
|
65
|
+
return undefined;
|
|
66
|
+
return { [headerName || "x-opencode-session"]: id };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Create a fetch wrapper that injects the session-id header into every request.
|
|
71
|
+
* @param {object} opts { send, headerName, sessionId, persistentId }
|
|
72
|
+
* @returns {typeof globalThis.fetch}
|
|
73
|
+
*/
|
|
74
|
+
export function createSessionHeaderFetch({ send, headerName, sessionId, persistentId }) {
|
|
75
|
+
if (send === false)
|
|
76
|
+
return globalThis.fetch;
|
|
77
|
+
const header = sessionHeaderOf({ send, headerName, sessionId, persistentId });
|
|
78
|
+
if (!header)
|
|
79
|
+
return globalThis.fetch;
|
|
80
|
+
return (async (input, init) => {
|
|
81
|
+
const next = init ? { ...init } : {};
|
|
82
|
+
next.headers = new Headers(init?.headers);
|
|
83
|
+
for (const [k, v] of Object.entries(header)) {
|
|
84
|
+
next.headers.set(k, v);
|
|
85
|
+
}
|
|
86
|
+
return globalThis.fetch(input, next);
|
|
87
|
+
});
|
|
88
|
+
}
|