@seele00/seele 0.1.63 → 0.1.65
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 +5 -3
- package/bin/seele-codex +1 -1
- package/libexec/seele-server +0 -0
- package/libexec/seele-worker +0 -0
- package/package.json +1 -4
- package/scripts/deploy/bootstrap.sh +14 -3
- package/scripts/deploy/start.sh +14 -9
- package/web/dist/assets/{abnfDiagram-VRR7QNED-DXJQwnn-.js → abnfDiagram-VRR7QNED-BB7DT0BN.js} +1 -1
- package/web/dist/assets/{arc-D_47-IET.js → arc-BlEU_mit.js} +1 -1
- package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-CKUldIzR.js → architectureDiagram-ZJ3FMSHR-Dy9cu2Mg.js} +1 -1
- package/web/dist/assets/{blockDiagram-677ZJIJ3-BD4Ym8Xi.js → blockDiagram-677ZJIJ3-DP4jMSfo.js} +1 -1
- package/web/dist/assets/{c4Diagram-LMCZKHZV-Cn268vLB.js → c4Diagram-LMCZKHZV-BtqFzX1w.js} +1 -1
- package/web/dist/assets/channel-mhSuRKJT.js +1 -0
- package/web/dist/assets/{chunk-2Q5K7J3B-D00lQ7mJ.js → chunk-2Q5K7J3B-BK9F5a0L.js} +1 -1
- package/web/dist/assets/{chunk-32BRIVSS-z7gv8Mry.js → chunk-32BRIVSS-nuQI6gtU.js} +1 -1
- package/web/dist/assets/{chunk-5VM5RSS4-BZJeO_rz.js → chunk-5VM5RSS4-D4IT05bt.js} +1 -1
- package/web/dist/assets/{chunk-EX3LRPZG-DoIg9UGx.js → chunk-EX3LRPZG-CrOtgxcr.js} +1 -1
- package/web/dist/assets/{chunk-JWPE2WC7-C1LcQus2.js → chunk-JWPE2WC7-Dn9JHm4W.js} +1 -1
- package/web/dist/assets/{chunk-MOJQB5TN--JPbFu4n.js → chunk-MOJQB5TN-VtD0_fGF.js} +1 -1
- package/web/dist/assets/{chunk-RYQCIY6F-BVv30W60.js → chunk-RYQCIY6F-TqRYsCot.js} +1 -1
- package/web/dist/assets/{chunk-V7JOEXUC-DYoSFgRT.js → chunk-V7JOEXUC-U9b5a7vL.js} +1 -1
- package/web/dist/assets/{chunk-VR4S4FIN-C8BRkTOa.js → chunk-VR4S4FIN-B3qLfeNJ.js} +1 -1
- package/web/dist/assets/{chunk-XXDRQBXY-CDfofIob.js → chunk-XXDRQBXY-DazVAZe-.js} +1 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-DYQSxD4g.js +1 -0
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-DYQSxD4g.js +1 -0
- package/web/dist/assets/{core-C10OFTno.js → core-2RdBW0rZ.js} +1 -1
- package/web/dist/assets/{cose-bilkent-JH36ORCC-g9E8J4Fz.js → cose-bilkent-JH36ORCC-vvKttQXU.js} +1 -1
- package/web/dist/assets/{cynefin-VYW2F7L2-Dc689veM.js → cynefin-VYW2F7L2-BKMZmA-n.js} +1 -1
- package/web/dist/assets/{cynefinDiagram-TSTJHNR4-BAAq_jvr.js → cynefinDiagram-TSTJHNR4-ckdzxzlr.js} +1 -1
- package/web/dist/assets/{dagre-VKFMJZFB-CPtiniZQ.js → dagre-VKFMJZFB-CZw8DTb1.js} +1 -1
- package/web/dist/assets/{diagram-FQU43EPY-CvbIL3lu.js → diagram-FQU43EPY-C06X0Kru.js} +1 -1
- package/web/dist/assets/{diagram-G47NLZAW-u5m78Utg.js → diagram-G47NLZAW-HX9CdauD.js} +1 -1
- package/web/dist/assets/{diagram-NH7WQ7WH-4f-Ipubv.js → diagram-NH7WQ7WH-Dlo1tIod.js} +1 -1
- package/web/dist/assets/{diagram-OA4YK3LP-SUl1EQ56.js → diagram-OA4YK3LP-C9GXFhgw.js} +1 -1
- package/web/dist/assets/{diagram-WEI45ONY-C_Upd46l.js → diagram-WEI45ONY-Ch1Xx234.js} +1 -1
- package/web/dist/assets/{ebnfDiagram-CCIWWBDH-CHp2D7Q9.js → ebnfDiagram-CCIWWBDH-Q0_rEUgk.js} +1 -1
- package/web/dist/assets/{erDiagram-Q63AITRT-DQliHxOw.js → erDiagram-Q63AITRT-BsDRdpx6.js} +1 -1
- package/web/dist/assets/{flowDiagram-23GEKE2U-BcOYSJFM.js → flowDiagram-23GEKE2U-DDFuMRJN.js} +1 -1
- package/web/dist/assets/{ganttDiagram-NO4QXBWP-CDLHtJq0.js → ganttDiagram-NO4QXBWP-Cjpm08-d.js} +1 -1
- package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-2j8C3mlk.js → gitGraphDiagram-IHSO6WYX-CnIosh2K.js} +1 -1
- package/web/dist/assets/index-eN6ddNRA.js +111 -0
- package/web/dist/assets/{infoDiagram-FWYZ7A6U-ClxdyQnM.js → infoDiagram-FWYZ7A6U-CH163HyC.js} +1 -1
- package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-Bc2nIRgb.js → ishikawaDiagram-FXEZZL3T-DkT-3n3D.js} +1 -1
- package/web/dist/assets/{journeyDiagram-5HDEW3XC-R-vJ00LW.js → journeyDiagram-5HDEW3XC-34TnH3wG.js} +1 -1
- package/web/dist/assets/{kanban-definition-HUTT4EX6-CR0s_Mo8.js → kanban-definition-HUTT4EX6-CJbOm0lN.js} +1 -1
- package/web/dist/assets/{linear-BQgrawZS.js → linear-CTKXTLwe.js} +1 -1
- package/web/dist/assets/{mermaid.core-faLMbjSU.js → mermaid.core-CAVP16_-.js} +4 -4
- package/web/dist/assets/{mindmap-definition-LN4V7U3C-BZULnQui.js → mindmap-definition-LN4V7U3C-rlppHZj_.js} +1 -1
- package/web/dist/assets/{pegDiagram-2B236MQR-DUm1p_1o.js → pegDiagram-2B236MQR-MbcWBNJi.js} +1 -1
- package/web/dist/assets/{pieDiagram-ENE6RG2P-r3LCASRK.js → pieDiagram-ENE6RG2P-DKU7a4tv.js} +1 -1
- package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-CGaCp0Px.js → quadrantDiagram-ABIIQ3AL-DpDsJVLi.js} +1 -1
- package/web/dist/assets/{railroadDiagram-RFXS5EU6-DmEKGO1A.js → railroadDiagram-RFXS5EU6-DrPM3aKC.js} +1 -1
- package/web/dist/assets/{requirementDiagram-TGXJPOKE-Byc4ivmp.js → requirementDiagram-TGXJPOKE-ZzS_iVag.js} +1 -1
- package/web/dist/assets/{sankeyDiagram-HTMAVEWB-BtJiL4zX.js → sankeyDiagram-HTMAVEWB-DrRrN0Lc.js} +1 -1
- package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-Bg3vdDGW.js → sequenceDiagram-DBY2YBRQ-CP8GBGZM.js} +1 -1
- package/web/dist/assets/{sizeCapture-X5ZJPWSS-CCRwjaWU.js → sizeCapture-X5ZJPWSS-BYVg_dQd.js} +1 -1
- package/web/dist/assets/{stateDiagram-2N3HPSRC-CQU-udox.js → stateDiagram-2N3HPSRC-CsJ3M80-.js} +1 -1
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-CaFOY1Xb.js +1 -0
- package/web/dist/assets/{swimlanes-5IMT3BWC-r3tJnQLJ.js → swimlanes-5IMT3BWC-XgRKQ20Q.js} +2 -2
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-DaKP_iDy.js +8 -0
- package/web/dist/assets/{timeline-definition-FHXFAJF6-DryYrdts.js → timeline-definition-FHXFAJF6-CU_Cq10d.js} +1 -1
- package/web/dist/assets/{vennDiagram-L72KCM5P-ZLPc0qvQ.js → vennDiagram-L72KCM5P-CLSDbg6o.js} +1 -1
- package/web/dist/assets/{wardleyDiagram-EHGQE667-RmgA6vQ9.js → wardleyDiagram-EHGQE667-DnAOuvzv.js} +1 -1
- package/web/dist/assets/{xychartDiagram-FW5EYKEG-BGIzispI.js → xychartDiagram-FW5EYKEG-CyC6V11l.js} +1 -1
- package/web/dist/index.html +1 -1
- package/codex/dist/app-server.js +0 -63
- package/codex/dist/errors.js +0 -16
- package/codex/dist/index.js +0 -4
- package/codex/dist/rpc-client.js +0 -96
- package/codex/dist/transports/stdio.js +0 -81
- package/codex/dist/types.js +0 -1
- package/codex/package.json +0 -12
- package/scripts/deploy/npm/postinstall.mjs +0 -10
- package/server/dist/auth/session.js +0 -71
- package/server/dist/auth/users.js +0 -276
- package/server/dist/codex-runtime/run-streamed-turn.js +0 -587
- package/server/dist/config/config.js +0 -71
- package/server/dist/contracts/artifact-rendering.js +0 -14
- package/server/dist/contracts/global-environment.js +0 -23
- package/server/dist/contracts/index.js +0 -114
- package/server/dist/contracts/managed-assets.js +0 -13
- package/server/dist/contracts/response-style.js +0 -23
- package/server/dist/contracts/task-clarification.js +0 -13
- package/server/dist/contracts/types.js +0 -1
- package/server/dist/contracts/wakeup.js +0 -13
- package/server/dist/contracts/workspace-boundary.js +0 -20
- package/server/dist/contracts/workspace-knowledge.js +0 -48
- package/server/dist/contracts/workspace-memory.js +0 -32
- package/server/dist/contracts/workspace-responsibility.js +0 -23
- package/server/dist/contracts/workspace-transcript.js +0 -26
- package/server/dist/conversations/knowledge.js +0 -380
- package/server/dist/conversations/store.js +0 -2466
- package/server/dist/doctor.js +0 -105
- package/server/dist/realtime/sse.js +0 -12
- package/server/dist/runtime-worker/client.js +0 -405
- package/server/dist/runtime-worker/process.js +0 -216
- package/server/dist/runtime-worker/protocol.js +0 -1
- package/server/dist/server.js +0 -4605
- package/server/dist/storage/sqlite.js +0 -39
- package/web/dist/assets/channel-Uz6zF6Xw.js +0 -1
- package/web/dist/assets/classDiagram-OUVF2IWQ-D6mpE1t2.js +0 -1
- package/web/dist/assets/classDiagram-v2-EOCWNBFH-D6mpE1t2.js +0 -1
- package/web/dist/assets/index-BqSosI7W.js +0 -111
- package/web/dist/assets/stateDiagram-v2-6OUMAXLB-YNSWW4ip.js +0 -1
- package/web/dist/assets/swimlanesDiagram-G3AALYLV-BGZAc11_.js +0 -8
|
@@ -1,380 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, } from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { randomInt } from "node:crypto";
|
|
4
|
-
import { getConversationWorkspaceDatabase, } from "./store.js";
|
|
5
|
-
import { runInTransaction } from "../storage/sqlite.js";
|
|
6
|
-
const KNOWLEDGE_ROOT = ".seele/knowledge";
|
|
7
|
-
const KNOWLEDGE_URI_ROOT = "seele://knowledge";
|
|
8
|
-
export function listWorkspaceKnowledge(conversation) {
|
|
9
|
-
migrateLegacyFileKnowledge(conversation);
|
|
10
|
-
const rows = getConversationWorkspaceDatabase(conversation)
|
|
11
|
-
.prepare("select data_json from workspace_knowledge order by updated_at desc")
|
|
12
|
-
.all();
|
|
13
|
-
return rows
|
|
14
|
-
.map((row) => parseStoredKnowledgeItem(conversation, row.data_json))
|
|
15
|
-
.filter((item) => item !== null)
|
|
16
|
-
.sort((left, right) => {
|
|
17
|
-
const attentionOrder = attentionRank(right.attention) - attentionRank(left.attention);
|
|
18
|
-
if (attentionOrder !== 0) {
|
|
19
|
-
return attentionOrder;
|
|
20
|
-
}
|
|
21
|
-
return right.updatedAt.localeCompare(left.updatedAt);
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
export function createWorkspaceKnowledge(conversation, input) {
|
|
25
|
-
const now = new Date().toISOString();
|
|
26
|
-
const id = createKnowledgeId(conversation);
|
|
27
|
-
const item = normalizeKnowledgeItem(conversation, {
|
|
28
|
-
id,
|
|
29
|
-
kind: parseKnowledgeKind(input.kind, "source"),
|
|
30
|
-
name: parseText(input.name, "Untitled knowledge"),
|
|
31
|
-
description: parseText(input.description),
|
|
32
|
-
purpose: parseText(input.purpose),
|
|
33
|
-
attention: parseKnowledgeAttention(input.attention, "tracked"),
|
|
34
|
-
refreshPolicy: parseKnowledgeRefreshPolicy(input.refreshPolicy, "manual"),
|
|
35
|
-
status: parseKnowledgeStatus(input.status, "draft"),
|
|
36
|
-
sourceClues: parseSourceClues(input.sourceClues, now),
|
|
37
|
-
fetch: {
|
|
38
|
-
type: "script",
|
|
39
|
-
scriptPath: relativeKnowledgePath(id, "fetch.sh"),
|
|
40
|
-
requiredEnv: parseRequiredEnv(input.requiredEnv),
|
|
41
|
-
verified: input.fetchVerified === true,
|
|
42
|
-
lastRunAt: parseNullableText(input.lastRunAt),
|
|
43
|
-
lastExitCode: typeof input.lastExitCode === "number"
|
|
44
|
-
? Math.trunc(input.lastExitCode)
|
|
45
|
-
: null,
|
|
46
|
-
lastContentHash: parseNullableText(input.lastContentHash),
|
|
47
|
-
},
|
|
48
|
-
rawPath: relativeKnowledgePath(id, "raw"),
|
|
49
|
-
digestPath: relativeKnowledgePath(id, "digest.md"),
|
|
50
|
-
skillPath: relativeKnowledgePath(id, "skill.md"),
|
|
51
|
-
createdAt: now,
|
|
52
|
-
updatedAt: now,
|
|
53
|
-
});
|
|
54
|
-
writeKnowledgeItem(conversation, item);
|
|
55
|
-
return item;
|
|
56
|
-
}
|
|
57
|
-
export function updateWorkspaceKnowledge(conversation, id, input) {
|
|
58
|
-
const existing = readKnowledgeItem(conversation, id);
|
|
59
|
-
if (!existing) {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
const item = normalizeKnowledgeItem(conversation, {
|
|
63
|
-
...existing,
|
|
64
|
-
kind: parseKnowledgeKind(input.kind, existing.kind),
|
|
65
|
-
name: Object.prototype.hasOwnProperty.call(input, "name")
|
|
66
|
-
? parseText(input.name, existing.name)
|
|
67
|
-
: existing.name,
|
|
68
|
-
description: Object.prototype.hasOwnProperty.call(input, "description")
|
|
69
|
-
? parseText(input.description)
|
|
70
|
-
: existing.description,
|
|
71
|
-
purpose: Object.prototype.hasOwnProperty.call(input, "purpose")
|
|
72
|
-
? parseText(input.purpose)
|
|
73
|
-
: existing.purpose,
|
|
74
|
-
attention: parseKnowledgeAttention(input.attention, existing.attention),
|
|
75
|
-
refreshPolicy: parseKnowledgeRefreshPolicy(input.refreshPolicy, existing.refreshPolicy),
|
|
76
|
-
status: parseKnowledgeStatus(input.status, existing.status),
|
|
77
|
-
sourceClues: Object.prototype.hasOwnProperty.call(input, "sourceClues")
|
|
78
|
-
? parseSourceClues(input.sourceClues, new Date().toISOString())
|
|
79
|
-
: existing.sourceClues,
|
|
80
|
-
fetch: {
|
|
81
|
-
...existing.fetch,
|
|
82
|
-
requiredEnv: Object.prototype.hasOwnProperty.call(input, "requiredEnv")
|
|
83
|
-
? parseRequiredEnv(input.requiredEnv)
|
|
84
|
-
: existing.fetch.requiredEnv,
|
|
85
|
-
verified: Object.prototype.hasOwnProperty.call(input, "fetchVerified")
|
|
86
|
-
? input.fetchVerified === true
|
|
87
|
-
: existing.fetch.verified,
|
|
88
|
-
lastRunAt: Object.prototype.hasOwnProperty.call(input, "lastRunAt")
|
|
89
|
-
? parseNullableText(input.lastRunAt)
|
|
90
|
-
: existing.fetch.lastRunAt,
|
|
91
|
-
lastExitCode: Object.prototype.hasOwnProperty.call(input, "lastExitCode")
|
|
92
|
-
? typeof input.lastExitCode === "number"
|
|
93
|
-
? Math.trunc(input.lastExitCode)
|
|
94
|
-
: null
|
|
95
|
-
: existing.fetch.lastExitCode,
|
|
96
|
-
lastContentHash: Object.prototype.hasOwnProperty.call(input, "lastContentHash")
|
|
97
|
-
? parseNullableText(input.lastContentHash)
|
|
98
|
-
: existing.fetch.lastContentHash,
|
|
99
|
-
},
|
|
100
|
-
updatedAt: new Date().toISOString(),
|
|
101
|
-
});
|
|
102
|
-
writeKnowledgeItem(conversation, item);
|
|
103
|
-
return item;
|
|
104
|
-
}
|
|
105
|
-
export function deleteWorkspaceKnowledge(conversation, id) {
|
|
106
|
-
migrateLegacyFileKnowledge(conversation);
|
|
107
|
-
const result = getConversationWorkspaceDatabase(conversation)
|
|
108
|
-
.prepare("delete from workspace_knowledge where id = ?")
|
|
109
|
-
.run(sanitizeKnowledgeId(id));
|
|
110
|
-
return result.changes > 0;
|
|
111
|
-
}
|
|
112
|
-
export function summarizeWorkspaceKnowledge(conversation) {
|
|
113
|
-
return listWorkspaceKnowledge(conversation).map((item) => ({
|
|
114
|
-
id: item.id,
|
|
115
|
-
kind: item.kind,
|
|
116
|
-
name: item.name,
|
|
117
|
-
purpose: item.purpose || item.description,
|
|
118
|
-
status: item.status,
|
|
119
|
-
attention: item.attention,
|
|
120
|
-
refreshPolicy: item.refreshPolicy,
|
|
121
|
-
rawPath: item.rawPath,
|
|
122
|
-
digestPath: item.digestPath,
|
|
123
|
-
skillPath: item.skillPath,
|
|
124
|
-
fetchScriptPath: item.fetch.scriptPath,
|
|
125
|
-
requiredEnv: item.fetch.requiredEnv,
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
function readKnowledgeItem(conversation, id) {
|
|
129
|
-
const safeId = sanitizeKnowledgeId(id);
|
|
130
|
-
if (!safeId) {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
migrateLegacyFileKnowledge(conversation);
|
|
134
|
-
const row = getConversationWorkspaceDatabase(conversation)
|
|
135
|
-
.prepare("select data_json from workspace_knowledge where id = ?")
|
|
136
|
-
.get(safeId);
|
|
137
|
-
return row?.data_json
|
|
138
|
-
? parseStoredKnowledgeItem(conversation, row.data_json)
|
|
139
|
-
: null;
|
|
140
|
-
}
|
|
141
|
-
function writeKnowledgeItem(conversation, item) {
|
|
142
|
-
getConversationWorkspaceDatabase(conversation)
|
|
143
|
-
.prepare(`
|
|
144
|
-
insert into workspace_knowledge (id, data_json, created_at, updated_at)
|
|
145
|
-
values (@id, @dataJson, @createdAt, @updatedAt)
|
|
146
|
-
on conflict(id) do update set
|
|
147
|
-
data_json = excluded.data_json,
|
|
148
|
-
updated_at = excluded.updated_at
|
|
149
|
-
`)
|
|
150
|
-
.run({
|
|
151
|
-
id: item.id,
|
|
152
|
-
dataJson: JSON.stringify(item),
|
|
153
|
-
createdAt: item.createdAt,
|
|
154
|
-
updatedAt: item.updatedAt,
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
function parseStoredKnowledgeItem(conversation, dataJson) {
|
|
158
|
-
try {
|
|
159
|
-
const value = JSON.parse(dataJson);
|
|
160
|
-
return normalizeKnowledgeItem(conversation, value);
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
return null;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
function migrateLegacyFileKnowledge(conversation) {
|
|
167
|
-
const db = getConversationWorkspaceDatabase(conversation);
|
|
168
|
-
const existing = db
|
|
169
|
-
.prepare("select count(*) as count from workspace_knowledge")
|
|
170
|
-
.get();
|
|
171
|
-
if (existing.count > 0) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
const root = workspaceKnowledgeRoot(conversation);
|
|
175
|
-
if (!existsSync(root)) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const legacyItems = readdirSync(root, { withFileTypes: true })
|
|
179
|
-
.filter((entry) => entry.isDirectory())
|
|
180
|
-
.map((entry) => readLegacyKnowledgeItem(conversation, entry.name))
|
|
181
|
-
.filter((item) => item !== null);
|
|
182
|
-
const insert = db.prepare(`
|
|
183
|
-
insert or ignore into workspace_knowledge (id, data_json, created_at, updated_at)
|
|
184
|
-
values (@id, @dataJson, @createdAt, @updatedAt)
|
|
185
|
-
`);
|
|
186
|
-
runInTransaction(db, () => {
|
|
187
|
-
for (const item of legacyItems) {
|
|
188
|
-
insert.run({
|
|
189
|
-
id: item.id,
|
|
190
|
-
dataJson: JSON.stringify(item),
|
|
191
|
-
createdAt: item.createdAt,
|
|
192
|
-
updatedAt: item.updatedAt,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
function readLegacyKnowledgeItem(conversation, id) {
|
|
198
|
-
const safeId = sanitizeKnowledgeId(id);
|
|
199
|
-
if (!safeId) {
|
|
200
|
-
return null;
|
|
201
|
-
}
|
|
202
|
-
const itemPath = path.join(workspaceKnowledgeItemRoot(conversation, safeId), "item.json");
|
|
203
|
-
if (!existsSync(itemPath)) {
|
|
204
|
-
return null;
|
|
205
|
-
}
|
|
206
|
-
try {
|
|
207
|
-
const value = JSON.parse(readFileSync(itemPath, "utf8"));
|
|
208
|
-
return normalizeKnowledgeItem(conversation, value);
|
|
209
|
-
}
|
|
210
|
-
catch {
|
|
211
|
-
return null;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
function normalizeKnowledgeItem(conversation, item) {
|
|
215
|
-
const now = new Date().toISOString();
|
|
216
|
-
const id = sanitizeKnowledgeId(item.id) || createKnowledgeId(conversation);
|
|
217
|
-
const createdAt = parseNullableText(item.createdAt) ?? now;
|
|
218
|
-
return {
|
|
219
|
-
id,
|
|
220
|
-
kind: parseKnowledgeKind(item.kind, "source"),
|
|
221
|
-
name: parseText(item.name, "Untitled knowledge"),
|
|
222
|
-
description: parseText(item.description),
|
|
223
|
-
purpose: parseText(item.purpose),
|
|
224
|
-
attention: parseKnowledgeAttention(item.attention, "tracked"),
|
|
225
|
-
refreshPolicy: parseKnowledgeRefreshPolicy(item.refreshPolicy, "manual"),
|
|
226
|
-
status: parseKnowledgeStatus(item.status, "draft"),
|
|
227
|
-
sourceClues: parseSourceClues(item.sourceClues, createdAt),
|
|
228
|
-
fetch: {
|
|
229
|
-
type: "script",
|
|
230
|
-
scriptPath: parseRelativeKnowledgePath(item.fetch?.scriptPath, id) ??
|
|
231
|
-
relativeKnowledgePath(id, "fetch.sh"),
|
|
232
|
-
requiredEnv: parseRequiredEnv(item.fetch?.requiredEnv),
|
|
233
|
-
verified: item.fetch?.verified === true,
|
|
234
|
-
lastRunAt: parseNullableText(item.fetch?.lastRunAt),
|
|
235
|
-
lastExitCode: typeof item.fetch?.lastExitCode === "number"
|
|
236
|
-
? Math.trunc(item.fetch.lastExitCode)
|
|
237
|
-
: null,
|
|
238
|
-
lastContentHash: parseNullableText(item.fetch?.lastContentHash),
|
|
239
|
-
},
|
|
240
|
-
rawPath: parseRelativeKnowledgePath(item.rawPath, id) ??
|
|
241
|
-
relativeKnowledgePath(id, "raw"),
|
|
242
|
-
digestPath: parseRelativeKnowledgePath(item.digestPath, id) ??
|
|
243
|
-
relativeKnowledgePath(id, "digest.md"),
|
|
244
|
-
skillPath: parseRelativeKnowledgePath(item.skillPath, id) ??
|
|
245
|
-
relativeKnowledgePath(id, "skill.md"),
|
|
246
|
-
createdAt,
|
|
247
|
-
updatedAt: parseNullableText(item.updatedAt) ?? createdAt,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
|
-
function createKnowledgeId(conversation) {
|
|
251
|
-
for (let index = 0; index < 50; index += 1) {
|
|
252
|
-
const id = randomInt(36 ** 6).toString(36).padStart(6, "0");
|
|
253
|
-
const row = getConversationWorkspaceDatabase(conversation)
|
|
254
|
-
.prepare("select id from workspace_knowledge where id = ?")
|
|
255
|
-
.get(id);
|
|
256
|
-
if (!row) {
|
|
257
|
-
return id;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return randomInt(36 ** 8).toString(36).padStart(8, "0");
|
|
261
|
-
}
|
|
262
|
-
function workspaceKnowledgeRoot(conversation) {
|
|
263
|
-
return path.join(conversation.workspacePath, KNOWLEDGE_ROOT);
|
|
264
|
-
}
|
|
265
|
-
function workspaceKnowledgeItemRoot(conversation, id) {
|
|
266
|
-
return path.join(workspaceKnowledgeRoot(conversation), sanitizeKnowledgeId(id));
|
|
267
|
-
}
|
|
268
|
-
function relativeKnowledgePath(id, leaf) {
|
|
269
|
-
return `${KNOWLEDGE_URI_ROOT}/${sanitizeKnowledgeId(id)}/${leaf}`;
|
|
270
|
-
}
|
|
271
|
-
function parseRelativeKnowledgePath(value, id) {
|
|
272
|
-
const text = parseText(value);
|
|
273
|
-
if (!text) {
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
const normalized = text.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
277
|
-
if (normalized.startsWith(`${KNOWLEDGE_ROOT}/${sanitizeKnowledgeId(id)}/`)) {
|
|
278
|
-
return normalized.replace(`${KNOWLEDGE_ROOT}/${sanitizeKnowledgeId(id)}`, `${KNOWLEDGE_URI_ROOT}/${sanitizeKnowledgeId(id)}`);
|
|
279
|
-
}
|
|
280
|
-
if (normalized.startsWith(`${KNOWLEDGE_URI_ROOT}/${sanitizeKnowledgeId(id)}/`)) {
|
|
281
|
-
return normalized;
|
|
282
|
-
}
|
|
283
|
-
return null;
|
|
284
|
-
}
|
|
285
|
-
function sanitizeKnowledgeId(value) {
|
|
286
|
-
return String(value ?? "")
|
|
287
|
-
.trim()
|
|
288
|
-
.toLowerCase()
|
|
289
|
-
.replace(/[^a-z0-9_-]/g, "")
|
|
290
|
-
.slice(0, 32);
|
|
291
|
-
}
|
|
292
|
-
function parseText(value, fallback = "") {
|
|
293
|
-
return typeof value === "string" ? value.trim() : fallback;
|
|
294
|
-
}
|
|
295
|
-
function parseNullableText(value) {
|
|
296
|
-
const text = parseText(value);
|
|
297
|
-
return text ? text : null;
|
|
298
|
-
}
|
|
299
|
-
function parseKnowledgeKind(value, fallback) {
|
|
300
|
-
return value === "source" || value === "skill" || value === "reference"
|
|
301
|
-
? value
|
|
302
|
-
: fallback;
|
|
303
|
-
}
|
|
304
|
-
function parseKnowledgeAttention(value, fallback) {
|
|
305
|
-
return value === "none" || value === "tracked" || value === "watch"
|
|
306
|
-
? value
|
|
307
|
-
: fallback;
|
|
308
|
-
}
|
|
309
|
-
function parseKnowledgeRefreshPolicy(value, fallback) {
|
|
310
|
-
return value === "manual" || value === "low-frequency-check"
|
|
311
|
-
? value
|
|
312
|
-
: fallback;
|
|
313
|
-
}
|
|
314
|
-
function parseKnowledgeStatus(value, fallback) {
|
|
315
|
-
return value === "draft" ||
|
|
316
|
-
value === "needs_credentials" ||
|
|
317
|
-
value === "invalid_credentials" ||
|
|
318
|
-
value === "needs_fetch_method" ||
|
|
319
|
-
value === "ready" ||
|
|
320
|
-
value === "stale_signal"
|
|
321
|
-
? value
|
|
322
|
-
: fallback;
|
|
323
|
-
}
|
|
324
|
-
function parseSourceClues(value, fallbackTime) {
|
|
325
|
-
if (!Array.isArray(value)) {
|
|
326
|
-
return [];
|
|
327
|
-
}
|
|
328
|
-
return value
|
|
329
|
-
.map((item) => {
|
|
330
|
-
if (!item || typeof item !== "object") {
|
|
331
|
-
return null;
|
|
332
|
-
}
|
|
333
|
-
const record = item;
|
|
334
|
-
const clueValue = parseText(record.value);
|
|
335
|
-
if (!clueValue) {
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
const providedBy = record.providedBy === "agent" || record.providedBy === "system"
|
|
339
|
-
? record.providedBy
|
|
340
|
-
: "user";
|
|
341
|
-
return {
|
|
342
|
-
type: parseText(record.type, "text"),
|
|
343
|
-
value: clueValue,
|
|
344
|
-
providedBy,
|
|
345
|
-
providedAt: parseNullableText(record.providedAt) ?? fallbackTime,
|
|
346
|
-
};
|
|
347
|
-
})
|
|
348
|
-
.filter((item) => item !== null);
|
|
349
|
-
}
|
|
350
|
-
function parseRequiredEnv(value) {
|
|
351
|
-
if (!Array.isArray(value)) {
|
|
352
|
-
return [];
|
|
353
|
-
}
|
|
354
|
-
return value
|
|
355
|
-
.map((item) => {
|
|
356
|
-
if (!item || typeof item !== "object") {
|
|
357
|
-
return null;
|
|
358
|
-
}
|
|
359
|
-
const record = item;
|
|
360
|
-
const key = parseText(record.key).toUpperCase();
|
|
361
|
-
if (!/^[A-Z_][A-Z0-9_]*$/.test(key)) {
|
|
362
|
-
return null;
|
|
363
|
-
}
|
|
364
|
-
return {
|
|
365
|
-
key,
|
|
366
|
-
description: parseText(record.description),
|
|
367
|
-
};
|
|
368
|
-
})
|
|
369
|
-
.filter((item) => item !== null)
|
|
370
|
-
.sort((left, right) => left.key.localeCompare(right.key));
|
|
371
|
-
}
|
|
372
|
-
function attentionRank(value) {
|
|
373
|
-
if (value === "watch") {
|
|
374
|
-
return 2;
|
|
375
|
-
}
|
|
376
|
-
if (value === "tracked") {
|
|
377
|
-
return 1;
|
|
378
|
-
}
|
|
379
|
-
return 0;
|
|
380
|
-
}
|