@markmo/europacore-session-ui 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/ArtifactsPage-BxaqShTv.js +1178 -0
- package/dist/{BoardPage-BAQrGP7G.js → BoardPage-DH7p5o99.js} +274 -265
- package/dist/{CardDetail-CCgP8R61.js → CardDetail-LfDCJQhS.js} +42 -33
- package/dist/{ComparePage-FcLLhKzC.js → ComparePage-CrbCyu4u.js} +33 -33
- package/dist/MemoriesPage-BRA53Hlb.js +679 -0
- package/dist/{OverviewPage-CbfbyGNT.js → OverviewPage-BSBqY83_.js} +50 -49
- package/dist/{RegisterPage-3-hJNQEV.js → RegisterPage-64yGl9E-.js} +76 -76
- package/dist/SessionPage-C4hSlxWQ.js +906 -0
- package/dist/api/agentClient.d.ts +66 -1
- package/dist/api/wire.d.ts +540 -4
- package/dist/features/artifacts/ArtifactDetail.d.ts +15 -0
- package/dist/features/artifacts/ArtifactDialogs.d.ts +29 -0
- package/dist/features/artifacts/ArtifactLedger.d.ts +11 -0
- package/dist/features/artifacts/ArtifactStats.d.ts +9 -0
- package/dist/features/artifacts/ArtifactsPage.d.ts +1 -0
- package/dist/features/artifacts/artifactsCommands.d.ts +3 -0
- package/dist/features/artifacts/artifactsStore.d.ts +27 -0
- package/dist/features/artifacts/artifactsUi.d.ts +33 -0
- package/dist/features/bootstrap.d.ts +1 -0
- package/dist/features/chat/model/artifactAccess.d.ts +50 -0
- package/dist/features/chat/model/artifactCsv.d.ts +11 -0
- package/dist/features/chat/model/artifactExport.d.ts +45 -0
- package/dist/features/chat/model/artifactStats.d.ts +79 -0
- package/dist/features/chat/model/artifacts.d.ts +151 -0
- package/dist/features/chat/model/claims.d.ts +102 -0
- package/dist/features/chat/model/contextSources.d.ts +41 -0
- package/dist/features/chat/model/entries.d.ts +37 -2
- package/dist/features/chat/model/fleet.d.ts +11 -0
- package/dist/features/chat/model/format.d.ts +6 -0
- package/dist/features/chat/model/inspect.d.ts +11 -0
- package/dist/features/chat/model/memory.d.ts +3 -3
- package/dist/features/chat/model/memoryRecords.d.ts +79 -0
- package/dist/features/chat/model/monitors.d.ts +11 -0
- package/dist/features/chat/model/progress.d.ts +73 -0
- package/dist/features/chat/model/routing.d.ts +20 -0
- package/dist/features/chat/model/store.d.ts +5 -0
- package/dist/features/chat/model/tasks.d.ts +1 -1
- package/dist/features/chat/panels/ProgressPanel.d.ts +8 -0
- package/dist/features/chat/session/ComposerHistory.d.ts +1 -1
- package/dist/features/chat/session/SessionController.d.ts +3 -2
- package/dist/features/chat/session/useFileMentions.d.ts +18 -5
- package/dist/features/chat/transcript/ArtifactCard.d.ts +8 -0
- package/dist/features/chat/transcript/Rows.d.ts +12 -1
- package/dist/features/commands/InspectDialog.d.ts +3 -0
- package/dist/features/commands/dialogs.d.ts +1 -1
- package/dist/features/commands/registry.d.ts +1 -1
- package/dist/features/memories/MemoriesPage.d.ts +1 -0
- package/dist/features/memories/memoriesCommands.d.ts +3 -0
- package/dist/features/memories/memoriesController.d.ts +81 -0
- package/dist/features/memory/MemoryDialog.d.ts +1 -1
- package/dist/features/memory/memoryService.d.ts +10 -10
- package/dist/features/workspace/claimsCommands.d.ts +26 -0
- package/dist/features/workspace/collisionsWatcher.d.ts +7 -0
- package/dist/features/workspace/useSessionPageHooks.d.ts +1 -1
- package/dist/{index-NjGO7Jg1.js → index-CMPf-3JZ.js} +4821 -3447
- package/dist/index.d.ts +2 -0
- package/dist/index.js +86 -82
- package/dist/lib/paths.d.ts +12 -0
- package/dist/lib/zip.d.ts +14 -0
- package/dist/{promptHistory-DjSCHmEk.js → promptHistory-BR0NpLCI.js} +14 -14
- package/package.json +1 -1
- package/dist/SessionPage-CA9hAakW.js +0 -865
|
@@ -0,0 +1,679 @@
|
|
|
1
|
+
import { jsxs as u, jsx as n, Fragment as H } from "react/jsx-runtime";
|
|
2
|
+
import { RefreshCw as Q, Search as Z, Brain as U, Pencil as ee, Trash2 as te, RotateCcw as se, History as ne } from "lucide-react";
|
|
3
|
+
import { useSyncExternalStore as ie, useMemo as re, useEffect as V, useState as S } from "react";
|
|
4
|
+
import { useSearchParams as oe } from "react-router";
|
|
5
|
+
import { bu as L, bw as g, bJ as ae, a2 as x, bi as v, b8 as A, n as J, H as le, g as ce, ad as de, aU as ue, Y as k, aK as _, aJ as K, o as C, a as R, V as X, B as P, bK as he } from "./index-CMPf-3JZ.js";
|
|
6
|
+
const me = ["org", "user", "project"], T = ["user", "feedback", "project", "reference"], F = 200, W = 4e3, fe = [
|
|
7
|
+
{ view: "stale", label: "Stale" },
|
|
8
|
+
{ view: "duplicate", label: "Duplicates" },
|
|
9
|
+
{ view: "never_recalled", label: "Never recalled" },
|
|
10
|
+
{ view: "over_cap", label: "Over index cap" },
|
|
11
|
+
{ view: "forgotten", label: "Forgotten" }
|
|
12
|
+
], Y = {
|
|
13
|
+
stale: { word: "STALE", letter: "S", label: "stale" },
|
|
14
|
+
duplicate: { word: "DUP", letter: "D", label: "duplicate" },
|
|
15
|
+
over_cap: { word: "OVERCAP", letter: "C", label: "over the index cap" },
|
|
16
|
+
never_recalled: { word: "UNUSED", letter: "N", label: "never recalled" },
|
|
17
|
+
kept: { word: "KEPT", letter: "K", label: "kept by a dream" }
|
|
18
|
+
};
|
|
19
|
+
function y(t) {
|
|
20
|
+
return t.status === "active";
|
|
21
|
+
}
|
|
22
|
+
function N(t, e) {
|
|
23
|
+
return y(t) && (t.flags ?? []).some((s) => s.flag === e);
|
|
24
|
+
}
|
|
25
|
+
function O(t, e, s) {
|
|
26
|
+
return t.key.scope === e && (e !== "project" || t.key.project_id === s);
|
|
27
|
+
}
|
|
28
|
+
function q(t, e) {
|
|
29
|
+
return e === "forgotten" ? !y(t) : N(t, e);
|
|
30
|
+
}
|
|
31
|
+
function pe(t) {
|
|
32
|
+
return `project ${t}`;
|
|
33
|
+
}
|
|
34
|
+
function ge(t, e, s, i) {
|
|
35
|
+
const a = t.filter(y), l = [{ id: "all", kind: "all", label: "All", count: a.length }];
|
|
36
|
+
for (const o of ["org", "user"]) {
|
|
37
|
+
const c = e[o];
|
|
38
|
+
c && l.push({
|
|
39
|
+
id: `scope:${o}`,
|
|
40
|
+
kind: "scope",
|
|
41
|
+
label: c,
|
|
42
|
+
scope: o,
|
|
43
|
+
count: a.filter((h) => O(h, o)).length
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
for (const o of s) {
|
|
47
|
+
const c = i.has(o) ? a.filter((h) => O(h, "project", o)).length : null;
|
|
48
|
+
l.push({
|
|
49
|
+
id: `scope:project:${o}`,
|
|
50
|
+
kind: "scope",
|
|
51
|
+
label: pe(o),
|
|
52
|
+
scope: "project",
|
|
53
|
+
project: o,
|
|
54
|
+
count: c
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
for (const { view: o, label: c } of fe)
|
|
58
|
+
l.push({ id: `view:${o}`, kind: "view", label: c, view: o, count: t.filter((h) => q(h, o)).length });
|
|
59
|
+
return l;
|
|
60
|
+
}
|
|
61
|
+
function B(t) {
|
|
62
|
+
return [me.indexOf(t.key.scope), T.indexOf(t.kind), t.name];
|
|
63
|
+
}
|
|
64
|
+
function xe(t, e) {
|
|
65
|
+
const [s, i] = [B(t), B(e)];
|
|
66
|
+
return s[0] - i[0] || s[1] - i[1] || s[2].localeCompare(i[2]);
|
|
67
|
+
}
|
|
68
|
+
function ye(t, e) {
|
|
69
|
+
const s = `${t.name} ${t.description} ${t.body}`.toLowerCase();
|
|
70
|
+
for (const i of e.toLowerCase().split(/\s+/).filter(Boolean))
|
|
71
|
+
if (i.startsWith("k:")) {
|
|
72
|
+
if (!t.kind.startsWith(i.slice(2))) return !1;
|
|
73
|
+
} else if (i.startsWith("s:")) {
|
|
74
|
+
if (!t.source.startsWith(i.slice(2))) return !1;
|
|
75
|
+
} else if (!s.includes(i)) return !1;
|
|
76
|
+
return !0;
|
|
77
|
+
}
|
|
78
|
+
function be(t, e, s, i = /* @__PURE__ */ new Set()) {
|
|
79
|
+
return e.filter((l) => t.kind === "view" ? q(l, t.view) || i.has(l.id) : !y(l) && !i.has(l.id) ? !1 : t.kind === "all" || O(l, t.scope, t.project)).filter((l) => !s || ye(l, s)).sort(xe);
|
|
80
|
+
}
|
|
81
|
+
function ve(t) {
|
|
82
|
+
const e = Y[t.flag].label;
|
|
83
|
+
return t.partner_name ? `${e} of ${t.partner_name}: ${t.detail}` : `${e}: ${t.detail}`;
|
|
84
|
+
}
|
|
85
|
+
function ke(t) {
|
|
86
|
+
if (t.status === "merged") return "never: merged into another memory";
|
|
87
|
+
if (t.status === "pruned") return "never: forgotten (r restores it)";
|
|
88
|
+
const e = t.tokens ? ` (${g(t.tokens.index)} tok)` : "", s = t.tokens ? ` (${g(t.tokens.body)} tok)` : "";
|
|
89
|
+
return N(t, "over_cap") ? `not in the index; its body when memory_search finds it${s}` : `index line on every call${e}; body when read, or when it matches a message${s}`;
|
|
90
|
+
}
|
|
91
|
+
function we(t, e = Date.now()) {
|
|
92
|
+
const s = t.session_id ? ` · session ${t.session_id.slice(0, 10)}` : "";
|
|
93
|
+
return `${t.source}${s} · ${L(t.created_at, e)}`;
|
|
94
|
+
}
|
|
95
|
+
const Ne = /^---[ \t]*\n([\s\S]*?)\n---[ \t]*(?:\n|$)/, $e = /^\s*([A-Za-z_][\w-]*)\s*:\s*(.*?)\s*$/;
|
|
96
|
+
function je(t) {
|
|
97
|
+
const e = Ne.exec(t.replace(/\r\n/g, `
|
|
98
|
+
`));
|
|
99
|
+
if (!e) return { error: "keep the frontmatter (the --- lines with name, description and type)" };
|
|
100
|
+
const s = /* @__PURE__ */ new Map();
|
|
101
|
+
for (const o of e[1].split(`
|
|
102
|
+
`)) {
|
|
103
|
+
const c = $e.exec(o);
|
|
104
|
+
c?.[2] && !s.has(c[1].toLowerCase()) && s.set(c[1].toLowerCase(), c[2].replace(/^(['"])(.*)\1$/, "$2"));
|
|
105
|
+
}
|
|
106
|
+
const i = (s.get("description") ?? "").replace(/\s+/g, " ").trim();
|
|
107
|
+
if (!i) return { error: "a memory needs a one-line description" };
|
|
108
|
+
if (i.length > F)
|
|
109
|
+
return { error: `keep the description under ${F} characters (it has ${i.length})` };
|
|
110
|
+
const a = (s.get("type") ?? "").toLowerCase();
|
|
111
|
+
if (!T.includes(a))
|
|
112
|
+
return { error: `type must be one of ${T.join(", ")}, not ${JSON.stringify(a)}` };
|
|
113
|
+
const l = t.replace(/\r\n/g, `
|
|
114
|
+
`).slice(e[0].length).trim();
|
|
115
|
+
return l.length > W ? { error: `keep the body under ${W} characters (it has ${l.length})` } : { name: s.get("name") ?? null, description: i, kind: a, body: l };
|
|
116
|
+
}
|
|
117
|
+
function Se(t, e) {
|
|
118
|
+
if (e.name !== null && e.name !== t.name)
|
|
119
|
+
return { error: `renaming is not supported: forget ${t.name} and save ${e.name} as a new memory` };
|
|
120
|
+
const s = {};
|
|
121
|
+
return e.kind !== t.kind && (s.kind = e.kind), e.description !== t.description && (s.description = e.description), e.body !== t.body.trim() && (s.body = e.body), Object.keys(s).length === 0 ? null : { ...s, revision: t.revision };
|
|
122
|
+
}
|
|
123
|
+
function M(t, e = 60) {
|
|
124
|
+
const s = String(t ?? "").replace(/\s+/g, " ").trim();
|
|
125
|
+
return s.length > e ? `${s.slice(0, e - 1)}…` : s;
|
|
126
|
+
}
|
|
127
|
+
function _e(t) {
|
|
128
|
+
const { before: e, after: s } = t;
|
|
129
|
+
if (!e) return ["created"];
|
|
130
|
+
if (!s) return [`forgotten: ${M(e.metadata && e.metadata.reason)}`];
|
|
131
|
+
const i = [];
|
|
132
|
+
for (const a of ["status", "kind", "description", "body", "kept_until"])
|
|
133
|
+
JSON.stringify(e[a]) !== JSON.stringify(s[a]) && i.push(`${a}: ${M(e[a]) || "—"} → ${M(s[a]) || "—"}`);
|
|
134
|
+
return i.length ? i : ["no change to its text"];
|
|
135
|
+
}
|
|
136
|
+
const Ce = [
|
|
137
|
+
{ key: "system", label: "system", glyph: "█", kinds: ["system_prompt"] },
|
|
138
|
+
{ key: "tools", label: "tools", glyph: "▓", kinds: ["tools"] },
|
|
139
|
+
{ key: "instructions", label: "instructions", glyph: "▒", kinds: ["instructions"] },
|
|
140
|
+
{ key: "memory", label: "memory", glyph: "░", kinds: ["memory_index", "memory_preload"] },
|
|
141
|
+
{ key: "other", label: "other", glyph: "▚", kinds: ["environment", "skill", "plan", "hook", "other"] },
|
|
142
|
+
{ key: "conversation", label: "conversation", glyph: "▪", kinds: ["conversation"] }
|
|
143
|
+
];
|
|
144
|
+
function Pe(t) {
|
|
145
|
+
return Ce.map((e) => ({
|
|
146
|
+
...e,
|
|
147
|
+
tokens: t.filter((s) => e.kinds.includes(s.kind)).reduce((s, i) => s + i.tokens, 0)
|
|
148
|
+
})).filter((e) => e.tokens > 0);
|
|
149
|
+
}
|
|
150
|
+
function Ee(t) {
|
|
151
|
+
const e = t.kind === "tools" ? `${t.items} definitions, ` : t.kind === "conversation" ? `${t.items} messages, ` : "";
|
|
152
|
+
return `(${t.label}: ${e}${g(t.tokens)} tok, not shown)`;
|
|
153
|
+
}
|
|
154
|
+
function Me(t) {
|
|
155
|
+
const e = [];
|
|
156
|
+
for (const s of t) {
|
|
157
|
+
const i = s.text ? ae(s.text).split(`
|
|
158
|
+
`) : [Ee(s)];
|
|
159
|
+
for (const [a, l] of i.entries()) e.push({ n: s.n, text: l, first: a === 0 });
|
|
160
|
+
}
|
|
161
|
+
return e;
|
|
162
|
+
}
|
|
163
|
+
function Le(t, e) {
|
|
164
|
+
return e ? ` (${Math.round(t * 100 / e)}% of the ${g(e)} window)` : "";
|
|
165
|
+
}
|
|
166
|
+
function Te(t, e, s) {
|
|
167
|
+
const i = [], a = t.filter((r) => r.kind === "memory_index").reduce((r, f) => r + f.tokens, 0), l = e.filter((r) => N(r, "never_recalled"));
|
|
168
|
+
if (a) {
|
|
169
|
+
const r = [`The memory index is ${g(a)} tok of every call${Le(a, s)}.`];
|
|
170
|
+
if (l.length) {
|
|
171
|
+
const f = l.reduce((p, w) => p + (w.tokens?.index ?? 0), 0);
|
|
172
|
+
r.push(`${l.length} never recalled in 30 days: ${g(f)} tok of it.`);
|
|
173
|
+
}
|
|
174
|
+
i.push({ title: "BUDGET", tone: "muted", lines: r });
|
|
175
|
+
}
|
|
176
|
+
const o = /* @__PURE__ */ new Map();
|
|
177
|
+
for (const r of e)
|
|
178
|
+
for (const f of r.flags ?? []) {
|
|
179
|
+
if (f.flag !== "duplicate" || !f.partner_name || !N(r, "duplicate")) continue;
|
|
180
|
+
const p = [r.name, f.partner_name].sort();
|
|
181
|
+
o.set(p.join("\0"), `${p[0]} ↔ ${p[1]}: ${f.detail}`);
|
|
182
|
+
}
|
|
183
|
+
o.size && i.push({ title: `DUPLICATES · ${o.size}`, tone: "accent", lines: [...o.values()] });
|
|
184
|
+
const c = e.filter((r) => N(r, "over_cap"));
|
|
185
|
+
c.length && i.push({
|
|
186
|
+
title: `OVER THE INDEX CAP · ${c.length}`,
|
|
187
|
+
tone: "warning",
|
|
188
|
+
lines: [`Only memory_search finds ${c.map((r) => r.name).join(", ")}.`]
|
|
189
|
+
});
|
|
190
|
+
const h = e.filter((r) => N(r, "stale"));
|
|
191
|
+
return h.length && i.push({
|
|
192
|
+
title: `STALE · ${h.length}`,
|
|
193
|
+
tone: "warning",
|
|
194
|
+
lines: ["Neither recalled nor changed in 90 days; a dream offers them for pruning."]
|
|
195
|
+
}), t.some((r) => r.status === "preview") && i.push({
|
|
196
|
+
title: "PREVIEW",
|
|
197
|
+
tone: "muted",
|
|
198
|
+
lines: ["The memory index is a preview: the session pins it at its first turn."]
|
|
199
|
+
}), i;
|
|
200
|
+
}
|
|
201
|
+
class Oe {
|
|
202
|
+
constructor(e, s) {
|
|
203
|
+
this.sessionId = e, this.contextSourcesServed = s, this.snapshot = this.view(0);
|
|
204
|
+
}
|
|
205
|
+
sessionId;
|
|
206
|
+
contextSourcesServed;
|
|
207
|
+
data = [];
|
|
208
|
+
statuses = [];
|
|
209
|
+
projectIds = [];
|
|
210
|
+
loadedProjects = /* @__PURE__ */ new Set();
|
|
211
|
+
changed = /* @__PURE__ */ new Set();
|
|
212
|
+
revisionList = null;
|
|
213
|
+
found = null;
|
|
214
|
+
note = "";
|
|
215
|
+
error = "";
|
|
216
|
+
busy = !1;
|
|
217
|
+
/** Answers to an earlier open are dropped. */
|
|
218
|
+
generation = 0;
|
|
219
|
+
project = null;
|
|
220
|
+
/** Edits the server refused, by memory, reopened by the next edit. */
|
|
221
|
+
drafts = /* @__PURE__ */ new Map();
|
|
222
|
+
listeners = /* @__PURE__ */ new Set();
|
|
223
|
+
snapshot;
|
|
224
|
+
view(e) {
|
|
225
|
+
return {
|
|
226
|
+
records: this.data,
|
|
227
|
+
statuses: this.statuses,
|
|
228
|
+
projects: this.projectIds,
|
|
229
|
+
loaded: new Set(this.loadedProjects),
|
|
230
|
+
kept: new Set(this.changed),
|
|
231
|
+
revisions: this.revisionList,
|
|
232
|
+
sources: this.found,
|
|
233
|
+
sourcesNote: this.note,
|
|
234
|
+
error: this.error,
|
|
235
|
+
busy: this.busy,
|
|
236
|
+
version: e
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
render() {
|
|
240
|
+
this.snapshot = this.view(this.snapshot.version + 1);
|
|
241
|
+
for (const e of this.listeners) e();
|
|
242
|
+
}
|
|
243
|
+
subscribe = (e) => (this.listeners.add(e), () => this.listeners.delete(e));
|
|
244
|
+
getSnapshot = () => this.snapshot;
|
|
245
|
+
/** The project whose memories open first: the session's. */
|
|
246
|
+
get sessionProject() {
|
|
247
|
+
return this.project;
|
|
248
|
+
}
|
|
249
|
+
// --- loading -----------------------------------------------------------------------------
|
|
250
|
+
/** Read everything afresh: the session's context first, for its project. */
|
|
251
|
+
async open() {
|
|
252
|
+
const e = ++this.generation;
|
|
253
|
+
this.changed.clear(), this.busy = !0, this.error = "", this.render(), await this.loadSources(), e === this.generation && (this.project = this.found?.memory?.scopes.find((s) => s.scope === "project")?.project_id ?? null, await this.load(e));
|
|
254
|
+
}
|
|
255
|
+
async load(e) {
|
|
256
|
+
try {
|
|
257
|
+
const [s, i] = await Promise.all([
|
|
258
|
+
x.memoryStatus(this.project),
|
|
259
|
+
x.memories({ project: this.project, status: "all" })
|
|
260
|
+
]);
|
|
261
|
+
if (e !== this.generation) return;
|
|
262
|
+
this.statuses = s.scopes, this.data = i, this.projectIds = [.../* @__PURE__ */ new Set([...this.project ? [this.project] : [], ...s.projects ?? []])], this.loadedProjects.clear(), this.project && this.loadedProjects.add(this.project), this.error = "";
|
|
263
|
+
} catch (s) {
|
|
264
|
+
e === this.generation && (this.error = `Could not read the memories: ${v(s)}`);
|
|
265
|
+
} finally {
|
|
266
|
+
e === this.generation && (this.busy = !1), this.render();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/** The session's context sources; why there are none when there aren't. */
|
|
270
|
+
async loadSources() {
|
|
271
|
+
if (!this.sessionId) {
|
|
272
|
+
this.found = null, this.note = "Open this from a session to see what it loads.", this.render();
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (!this.contextSourcesServed()) {
|
|
276
|
+
this.found = null, this.note = "This server does not list a session's context sources (needs a newer europacore).", this.render();
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
try {
|
|
280
|
+
this.found = await x.contextSources(this.sessionId), this.note = "";
|
|
281
|
+
} catch (e) {
|
|
282
|
+
this.found = null, this.note = e instanceof A && e.status === 409 ? "This session's agent does not report its context." : `Could not read the session's context: ${v(e)}`;
|
|
283
|
+
}
|
|
284
|
+
this.render();
|
|
285
|
+
}
|
|
286
|
+
/** Read everything again, keeping the projects opened and the memories changed here. */
|
|
287
|
+
async reload() {
|
|
288
|
+
const e = ++this.generation, s = [...this.loadedProjects].filter((i) => i !== this.project);
|
|
289
|
+
this.busy = !0, this.render(), await this.load(e);
|
|
290
|
+
for (const i of s) await this.loadProject(i);
|
|
291
|
+
}
|
|
292
|
+
/** Another of the caller's projects, read when its scope is first chosen; what went wrong, or null. */
|
|
293
|
+
async loadProject(e) {
|
|
294
|
+
let s = null;
|
|
295
|
+
try {
|
|
296
|
+
const [i, a] = await Promise.all([x.memoryStatus(e), x.memories({ scope: "project", project: e, status: "all" })]), l = (c) => c.key.scope === "project" && c.key.project_id === e;
|
|
297
|
+
this.data = [...this.data.filter((c) => !l(c)), ...a];
|
|
298
|
+
const o = i.scopes.find((c) => c.scope === "project");
|
|
299
|
+
o && (this.statuses = [...this.statuses.filter((c) => c.project_id !== e), o]), this.loadedProjects.add(e);
|
|
300
|
+
} catch (i) {
|
|
301
|
+
s = `Could not read ${e}'s memories: ${v(i)}`;
|
|
302
|
+
}
|
|
303
|
+
return this.render(), s;
|
|
304
|
+
}
|
|
305
|
+
async history(e) {
|
|
306
|
+
this.revisionList = null, this.render();
|
|
307
|
+
try {
|
|
308
|
+
return this.revisionList = await x.memoryRevisions(e.id), null;
|
|
309
|
+
} catch (s) {
|
|
310
|
+
return this.revisionList = [], { ok: !1, message: `Could not read its history: ${v(s)}` };
|
|
311
|
+
} finally {
|
|
312
|
+
this.render();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
closeHistory() {
|
|
316
|
+
this.revisionList = null, this.render();
|
|
317
|
+
}
|
|
318
|
+
// --- changes -------------------------------------------------------------------------------
|
|
319
|
+
replace(e) {
|
|
320
|
+
this.data = this.data.map((s) => s.id === e.id ? e : s), this.changed.add(e.id);
|
|
321
|
+
}
|
|
322
|
+
async forget(e) {
|
|
323
|
+
if (!y(e)) return { ok: !1, message: `${e.name} is already ${e.status === "merged" ? "merged" : "forgotten"}` };
|
|
324
|
+
try {
|
|
325
|
+
return this.replace(await x.forgetMemory(e.id, "forgotten in the web")), this.reload(), { ok: !0, message: `Forgot ${e.name}; Restore brings it back` };
|
|
326
|
+
} catch (s) {
|
|
327
|
+
return { ok: !1, message: `Could not forget ${e.name}: ${v(s)}` };
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
async restore(e) {
|
|
331
|
+
if (y(e)) return { ok: !1, message: `${e.name} is not forgotten` };
|
|
332
|
+
try {
|
|
333
|
+
return this.replace(await x.restoreMemory(e.id)), this.reload(), { ok: !0, message: `Restored ${e.name}` };
|
|
334
|
+
} catch (s) {
|
|
335
|
+
return { ok: !1, message: `Could not restore ${e.name}: ${v(s)}` };
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* What an edit starts from: the draft the server refused last time, else the memory as markdown, read afresh;
|
|
340
|
+
* with the record read, whose revision the save is made against.
|
|
341
|
+
*/
|
|
342
|
+
async startEdit(e) {
|
|
343
|
+
if (!y(e)) return { ok: !1, message: `${e.name} is ${e.status}: restore it first` };
|
|
344
|
+
try {
|
|
345
|
+
const s = await x.memory(e.id), i = this.drafts.get(e.id);
|
|
346
|
+
return { text: i ?? s.markdown ?? "", current: s, draft: i !== void 0 };
|
|
347
|
+
} catch (s) {
|
|
348
|
+
return { ok: !1, message: `Could not read ${e.name}: ${v(s)}` };
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/** Save an edit against the revision read; one refused is kept as the draft the next edit reopens. */
|
|
352
|
+
async save(e, s) {
|
|
353
|
+
const i = (o) => (this.drafts.set(e.id, s), { ok: !1, message: `Not saved: ${o}. Edit reopens your text.` }), a = je(s);
|
|
354
|
+
if ("error" in a) return i(a.error);
|
|
355
|
+
const l = Se(e, a);
|
|
356
|
+
if (l === null)
|
|
357
|
+
return this.drafts.delete(e.id), { ok: !0, message: "No changes" };
|
|
358
|
+
if ("error" in l) return i(l.error);
|
|
359
|
+
try {
|
|
360
|
+
const o = await x.updateMemory(e.id, l);
|
|
361
|
+
return this.drafts.delete(e.id), this.replace(o), this.reload(), { ok: !0, message: `Saved ${o.name} (revision ${o.revision})` };
|
|
362
|
+
} catch (o) {
|
|
363
|
+
const c = o instanceof A && o.code === "memory_changed";
|
|
364
|
+
return i(c ? "it changed since you opened it" : v(o));
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/** Throw away a refused edit. */
|
|
368
|
+
dropDraft(e) {
|
|
369
|
+
this.drafts.delete(e);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function z(t) {
|
|
373
|
+
return ie(t.subscribe, t.getSnapshot);
|
|
374
|
+
}
|
|
375
|
+
function G({ record: t }) {
|
|
376
|
+
return y(t) ? /* @__PURE__ */ n(H, { children: (t.flags ?? []).map((e) => /* @__PURE__ */ n(P, { tone: e.flag === "kept" ? "ok" : e.flag === "never_recalled" ? "neutral" : "warn", children: Y[e.flag].label }, e.flag)) }) : /* @__PURE__ */ n(P, { tone: "neutral", children: t.status === "merged" ? "Merged" : "Forgotten" });
|
|
377
|
+
}
|
|
378
|
+
function Re({ nodes: t, selected: e, onSelect: s }) {
|
|
379
|
+
const i = t.filter((o) => o.kind !== "view"), a = t.filter((o) => o.kind === "view"), l = (o) => /* @__PURE__ */ n("li", { children: /* @__PURE__ */ u(
|
|
380
|
+
"button",
|
|
381
|
+
{
|
|
382
|
+
type: "button",
|
|
383
|
+
onClick: () => s(o),
|
|
384
|
+
"aria-current": o.id === e || void 0,
|
|
385
|
+
className: R(
|
|
386
|
+
"flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-[13px]",
|
|
387
|
+
o.id === e ? "bg-accent-soft font-semibold text-accent" : "text-ink hover:bg-surface-hover"
|
|
388
|
+
),
|
|
389
|
+
children: [
|
|
390
|
+
/* @__PURE__ */ n("span", { className: "min-w-0 flex-1 truncate", children: o.label }),
|
|
391
|
+
/* @__PURE__ */ n("span", { className: "text-[11.5px] text-muted tabular-nums", children: o.count ?? "…" })
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
) }, o.id);
|
|
395
|
+
return /* @__PURE__ */ u("nav", { "aria-label": "Scopes", className: "flex flex-col gap-3", children: [
|
|
396
|
+
/* @__PURE__ */ n("ul", { className: "flex flex-col gap-0.5", children: i.map(l) }),
|
|
397
|
+
/* @__PURE__ */ u("div", { children: [
|
|
398
|
+
/* @__PURE__ */ n("h3", { className: "px-2.5 pb-1 text-[11px] font-semibold tracking-wider text-muted uppercase", children: "Smart views" }),
|
|
399
|
+
/* @__PURE__ */ n("ul", { className: "flex flex-col gap-0.5", children: a.map(l) })
|
|
400
|
+
] })
|
|
401
|
+
] });
|
|
402
|
+
}
|
|
403
|
+
function ze({ controller: t, record: e }) {
|
|
404
|
+
const { toast: s } = J(), i = z(t), [a, l] = S(null), [o, c] = S(!1), [h, r] = S(!1);
|
|
405
|
+
V(() => {
|
|
406
|
+
l(null), c(!1), t.closeHistory();
|
|
407
|
+
}, [e.id]);
|
|
408
|
+
const f = async (m) => {
|
|
409
|
+
r(!0);
|
|
410
|
+
try {
|
|
411
|
+
const b = await m();
|
|
412
|
+
b && s(b.message, b.ok ? "ok" : "danger");
|
|
413
|
+
} finally {
|
|
414
|
+
r(!1);
|
|
415
|
+
}
|
|
416
|
+
}, p = () => f(async () => {
|
|
417
|
+
const m = await t.startEdit(e);
|
|
418
|
+
return "ok" in m ? m : (l(m), m.draft ? { ok: !1, message: "Reopened the edit the server refused" } : null);
|
|
419
|
+
}), w = () => f(async () => {
|
|
420
|
+
if (!a) return null;
|
|
421
|
+
const m = await t.save(a.current, a.text);
|
|
422
|
+
return m.ok && l(null), m;
|
|
423
|
+
}), $ = y(e);
|
|
424
|
+
return /* @__PURE__ */ u("article", { className: "flex flex-col gap-3", children: [
|
|
425
|
+
/* @__PURE__ */ u("header", { className: "flex flex-col gap-1", children: [
|
|
426
|
+
/* @__PURE__ */ u("div", { className: "flex flex-wrap items-center gap-1.5", children: [
|
|
427
|
+
/* @__PURE__ */ n(P, { tone: "accent", children: e.kind }),
|
|
428
|
+
/* @__PURE__ */ n("span", { className: "text-[12px] text-muted", children: e.key.scope === "project" ? `project ${e.key.project_id ?? ""}` : e.key.scope }),
|
|
429
|
+
/* @__PURE__ */ n(G, { record: e })
|
|
430
|
+
] }),
|
|
431
|
+
/* @__PURE__ */ n("h2", { className: "font-mono text-[15px] font-semibold break-words text-ink", children: e.name }),
|
|
432
|
+
/* @__PURE__ */ n("p", { className: "text-[13px] text-ink", children: C(e.description) }),
|
|
433
|
+
/* @__PURE__ */ u("p", { className: "text-[12px] text-muted", children: [
|
|
434
|
+
we(e),
|
|
435
|
+
" · revision ",
|
|
436
|
+
e.revision,
|
|
437
|
+
" · recalled ",
|
|
438
|
+
e.recall_count,
|
|
439
|
+
"×",
|
|
440
|
+
e.last_recalled_at ? `, last ${L(e.last_recalled_at)}` : ""
|
|
441
|
+
] })
|
|
442
|
+
] }),
|
|
443
|
+
/* @__PURE__ */ u("div", { className: "flex flex-wrap gap-1.5", children: [
|
|
444
|
+
$ ? /* @__PURE__ */ u(H, { children: [
|
|
445
|
+
/* @__PURE__ */ n(k, { size: "sm", icon: /* @__PURE__ */ n(ee, { size: 14 }), disabled: h || a !== null, onClick: () => {
|
|
446
|
+
p();
|
|
447
|
+
}, children: "Edit" }),
|
|
448
|
+
/* @__PURE__ */ n(k, { size: "sm", variant: "danger", icon: /* @__PURE__ */ n(te, { size: 14 }), disabled: h, onClick: () => {
|
|
449
|
+
f(() => t.forget(e));
|
|
450
|
+
}, children: "Forget" })
|
|
451
|
+
] }) : /* @__PURE__ */ n(k, { size: "sm", icon: /* @__PURE__ */ n(se, { size: 14 }), disabled: h, onClick: () => {
|
|
452
|
+
f(() => t.restore(e));
|
|
453
|
+
}, children: "Restore" }),
|
|
454
|
+
/* @__PURE__ */ n(
|
|
455
|
+
k,
|
|
456
|
+
{
|
|
457
|
+
size: "sm",
|
|
458
|
+
variant: "ghost",
|
|
459
|
+
icon: /* @__PURE__ */ n(ne, { size: 14 }),
|
|
460
|
+
onClick: () => {
|
|
461
|
+
c((m) => !m), o || f(() => t.history(e));
|
|
462
|
+
},
|
|
463
|
+
children: "History"
|
|
464
|
+
}
|
|
465
|
+
)
|
|
466
|
+
] }),
|
|
467
|
+
/* @__PURE__ */ u("dl", { className: "grid grid-cols-[96px_1fr] gap-x-2 gap-y-1 text-[12.5px]", children: [
|
|
468
|
+
/* @__PURE__ */ n("dt", { className: "text-muted", children: "Loads" }),
|
|
469
|
+
/* @__PURE__ */ n("dd", { className: "text-ink", children: ke(e) })
|
|
470
|
+
] }),
|
|
471
|
+
$ && (e.flags ?? []).map((m) => /* @__PURE__ */ n(_, { tone: m.flag === "kept" ? "ok" : "warn", children: ve(m) }, m.flag)),
|
|
472
|
+
a ? /* @__PURE__ */ u("div", { className: "flex flex-col gap-2", children: [
|
|
473
|
+
/* @__PURE__ */ u("p", { className: "text-[12px] text-muted", children: [
|
|
474
|
+
"The memory as the server keeps it: frontmatter (name, description, type) and its body. Saved against revision ",
|
|
475
|
+
a.current.revision,
|
|
476
|
+
"."
|
|
477
|
+
] }),
|
|
478
|
+
/* @__PURE__ */ n(
|
|
479
|
+
"textarea",
|
|
480
|
+
{
|
|
481
|
+
"aria-label": "The memory as markdown",
|
|
482
|
+
value: a.text,
|
|
483
|
+
onChange: (m) => l({ ...a, text: m.target.value }),
|
|
484
|
+
rows: 14,
|
|
485
|
+
spellCheck: !1,
|
|
486
|
+
className: "w-full rounded-md border border-line bg-surface px-2.5 py-2 font-mono text-[12.5px] text-ink focus:border-accent focus:ring-2 focus:ring-accent/20 focus:outline-none"
|
|
487
|
+
}
|
|
488
|
+
),
|
|
489
|
+
/* @__PURE__ */ u("div", { className: "flex justify-end gap-2", children: [
|
|
490
|
+
/* @__PURE__ */ n(
|
|
491
|
+
k,
|
|
492
|
+
{
|
|
493
|
+
size: "sm",
|
|
494
|
+
variant: "ghost",
|
|
495
|
+
onClick: () => {
|
|
496
|
+
t.dropDraft(e.id), l(null);
|
|
497
|
+
},
|
|
498
|
+
children: "Discard"
|
|
499
|
+
}
|
|
500
|
+
),
|
|
501
|
+
/* @__PURE__ */ n(k, { size: "sm", variant: "primary", loading: h, onClick: () => {
|
|
502
|
+
w();
|
|
503
|
+
}, children: "Save" })
|
|
504
|
+
] })
|
|
505
|
+
] }) : /* @__PURE__ */ n("div", { className: "rounded-lg border border-line-soft bg-surface-alt px-3 py-2 text-[13px]", children: /* @__PURE__ */ n(he, { content: e.body }) }),
|
|
506
|
+
o && /* @__PURE__ */ u("section", { children: [
|
|
507
|
+
/* @__PURE__ */ n("h3", { className: "mb-1.5 text-[11px] font-semibold tracking-wider text-muted uppercase", children: "History" }),
|
|
508
|
+
i.revisions === null ? /* @__PURE__ */ n(K, { size: "sm", className: "text-accent" }) : i.revisions.length ? /* @__PURE__ */ n("ol", { className: "flex flex-col gap-1.5", children: i.revisions.map((m) => /* @__PURE__ */ u("li", { className: "rounded-md border border-line-soft px-2.5 py-1.5 text-[12px]", children: [
|
|
509
|
+
/* @__PURE__ */ u("div", { className: "text-muted", children: [
|
|
510
|
+
"r",
|
|
511
|
+
m.revision,
|
|
512
|
+
" · ",
|
|
513
|
+
m.op,
|
|
514
|
+
" · ",
|
|
515
|
+
m.actor,
|
|
516
|
+
m.dream_id ? " (a dream)" : "",
|
|
517
|
+
" · ",
|
|
518
|
+
L(m.created_at)
|
|
519
|
+
] }),
|
|
520
|
+
/* @__PURE__ */ n("ul", { className: "mt-0.5 text-ink", children: _e(m).map((b) => /* @__PURE__ */ n("li", { className: "break-words", children: b }, b)) })
|
|
521
|
+
] }, m.id)) }) : /* @__PURE__ */ n("p", { className: "text-[12.5px] text-muted", children: "No history." })
|
|
522
|
+
] })
|
|
523
|
+
] });
|
|
524
|
+
}
|
|
525
|
+
function De({ controller: t }) {
|
|
526
|
+
const e = z(t), [s, i] = S(!1), a = e.sources;
|
|
527
|
+
if (!a)
|
|
528
|
+
return /* @__PURE__ */ n("div", { className: "rounded-xl border border-line bg-surface", children: /* @__PURE__ */ n(X, { icon: /* @__PURE__ */ n(U, { size: 20 }), title: "No context to show", children: e.sourcesNote || "Loading…" }) });
|
|
529
|
+
const l = a.context_window, o = l ?? Math.max(1, a.estimated_tokens), c = Pe(a.sources), h = Te(a.sources, e.records, l);
|
|
530
|
+
return /* @__PURE__ */ u("div", { className: "flex flex-col gap-4", children: [
|
|
531
|
+
/* @__PURE__ */ u("section", { className: "rounded-xl border border-line bg-surface p-3.5", children: [
|
|
532
|
+
/* @__PURE__ */ u("div", { className: "mb-2 flex flex-wrap items-baseline justify-between gap-2 text-[12.5px]", children: [
|
|
533
|
+
/* @__PURE__ */ u("h3", { className: "font-semibold text-ink", children: [
|
|
534
|
+
"What ",
|
|
535
|
+
a.model ? C(a.model) : "the model",
|
|
536
|
+
" reads"
|
|
537
|
+
] }),
|
|
538
|
+
/* @__PURE__ */ u("span", { className: "text-muted tabular-nums", children: [
|
|
539
|
+
"≈",
|
|
540
|
+
g(a.estimated_tokens),
|
|
541
|
+
" tokens",
|
|
542
|
+
l ? ` of ${g(l)}` : ""
|
|
543
|
+
] })
|
|
544
|
+
] }),
|
|
545
|
+
/* @__PURE__ */ n("ul", { className: "flex flex-col gap-1.5", children: c.map((r) => /* @__PURE__ */ u("li", { className: "grid grid-cols-[110px_1fr_90px] items-center gap-2 text-[12.5px]", children: [
|
|
546
|
+
/* @__PURE__ */ n("span", { className: "text-ink", children: r.label }),
|
|
547
|
+
/* @__PURE__ */ n("span", { className: "h-2.5 overflow-hidden rounded-full bg-surface-sunken", "aria-hidden": "true", children: /* @__PURE__ */ n("span", { className: "block h-full rounded-r-[4px] bg-accent", style: { width: `${Math.max(0.5, r.tokens / o * 100)}%` } }) }),
|
|
548
|
+
/* @__PURE__ */ u("span", { className: "text-right text-muted tabular-nums", children: [
|
|
549
|
+
g(r.tokens),
|
|
550
|
+
l ? ` · ${Math.round(r.tokens / l * 100)}%` : ""
|
|
551
|
+
] })
|
|
552
|
+
] }, r.key)) })
|
|
553
|
+
] }),
|
|
554
|
+
h.length > 0 && /* @__PURE__ */ n("div", { className: "grid gap-3 md:grid-cols-2", children: h.map((r) => /* @__PURE__ */ n(_, { tone: r.tone === "warning" ? "warn" : "info", title: r.title, children: /* @__PURE__ */ n("ul", { className: "space-y-0.5", children: r.lines.map((f) => /* @__PURE__ */ n("li", { children: f }, f)) }) }, r.title)) }),
|
|
555
|
+
/* @__PURE__ */ u("section", { className: "rounded-xl border border-line bg-surface", children: [
|
|
556
|
+
/* @__PURE__ */ u("div", { className: "flex items-center justify-between border-b border-line px-3.5 py-2", children: [
|
|
557
|
+
/* @__PURE__ */ n("h3", { className: "text-[12.5px] font-semibold text-ink", children: "Sources, in load order" }),
|
|
558
|
+
/* @__PURE__ */ u("label", { className: "flex items-center gap-1.5 text-[12.5px] text-ink", children: [
|
|
559
|
+
/* @__PURE__ */ n("input", { type: "checkbox", checked: s, onChange: (r) => i(r.target.checked) }),
|
|
560
|
+
"Merged text"
|
|
561
|
+
] })
|
|
562
|
+
] }),
|
|
563
|
+
s ? /* @__PURE__ */ n("pre", { className: "max-h-[60vh] overflow-auto px-3.5 py-2 font-mono text-[11.5px] leading-[1.5] whitespace-pre-wrap text-ink", children: Me(a.sources).map((r, f) => (
|
|
564
|
+
// biome-ignore lint/suspicious/noArrayIndexKey: the merged text's lines, in order
|
|
565
|
+
/* @__PURE__ */ u("div", { className: R("grid grid-cols-[2.5rem_1fr] gap-2", r.first && "mt-1 border-t border-line-soft pt-1"), children: [
|
|
566
|
+
/* @__PURE__ */ n("span", { className: "text-right text-faint select-none", children: r.first ? r.n : "" }),
|
|
567
|
+
/* @__PURE__ */ n("span", { children: r.text })
|
|
568
|
+
] }, f)
|
|
569
|
+
)) }) : /* @__PURE__ */ n("ol", { className: "divide-y divide-line-soft", children: a.sources.map((r) => /* @__PURE__ */ u("li", { className: "flex items-center gap-2 px-3.5 py-1.5 text-[12.5px]", children: [
|
|
570
|
+
/* @__PURE__ */ n("span", { className: "w-6 text-right text-faint tabular-nums", children: r.n }),
|
|
571
|
+
/* @__PURE__ */ n("span", { className: "min-w-0 flex-1 truncate text-ink", children: C(r.label) }),
|
|
572
|
+
r.status !== "sent" && /* @__PURE__ */ n(P, { tone: "neutral", children: r.status }),
|
|
573
|
+
/* @__PURE__ */ n("span", { className: "text-muted tabular-nums", children: g(r.tokens) })
|
|
574
|
+
] }, r.id)) })
|
|
575
|
+
] })
|
|
576
|
+
] });
|
|
577
|
+
}
|
|
578
|
+
function He() {
|
|
579
|
+
const { toast: t } = J(), [e, s] = oe(), i = e.get("session"), a = e.get("view") ?? "browse", l = e.get("q") ?? "", o = le((d) => d.info?.capabilities.memory), c = re(() => new Oe(i, () => ce().info?.capabilities.context_sources !== !1), [i]), h = z(c);
|
|
580
|
+
V(() => {
|
|
581
|
+
c.open();
|
|
582
|
+
}, [c]);
|
|
583
|
+
const r = (d) => s(
|
|
584
|
+
(j) => {
|
|
585
|
+
const E = new URLSearchParams(j);
|
|
586
|
+
for (const [D, I] of Object.entries(d))
|
|
587
|
+
I === null ? E.delete(D) : E.set(D, I);
|
|
588
|
+
return E;
|
|
589
|
+
},
|
|
590
|
+
{ replace: !0 }
|
|
591
|
+
), f = Object.fromEntries(h.statuses.filter((d) => d.scope !== "project").map((d) => [d.scope, d.label])), p = ge(h.records, f, h.projects, h.loaded), w = p.find((d) => d.id === e.get("scope")) ?? p[0], $ = be(w, h.records, l, h.kept), m = h.records.find((d) => d.id === e.get("id")) ?? null, b = (d) => {
|
|
592
|
+
r({ scope: d.id, id: null }), d.kind === "scope" && d.scope === "project" && d.project && !h.loaded.has(d.project) && c.loadProject(d.project).then((j) => j && t(j, "danger"));
|
|
593
|
+
};
|
|
594
|
+
return /* @__PURE__ */ u("div", { className: "min-h-full bg-bg", children: [
|
|
595
|
+
/* @__PURE__ */ n(
|
|
596
|
+
de,
|
|
597
|
+
{
|
|
598
|
+
eyebrow: "Memory",
|
|
599
|
+
title: "Long-term memories",
|
|
600
|
+
subtitle: `What agents remember between sessions${c.sessionProject ? ` · ${c.sessionProject}` : ""}. Decisions and requirements are in the decision register.`,
|
|
601
|
+
actions: /* @__PURE__ */ u("div", { className: "flex items-center gap-2", children: [
|
|
602
|
+
/* @__PURE__ */ n(
|
|
603
|
+
ue,
|
|
604
|
+
{
|
|
605
|
+
label: "View",
|
|
606
|
+
value: a,
|
|
607
|
+
onChange: (d) => {
|
|
608
|
+
r({ view: d === "browse" ? null : d }), d === "context" && c.loadSources();
|
|
609
|
+
},
|
|
610
|
+
options: [
|
|
611
|
+
{ value: "browse", label: "Memories" },
|
|
612
|
+
{ value: "context", label: "Context" }
|
|
613
|
+
]
|
|
614
|
+
}
|
|
615
|
+
),
|
|
616
|
+
/* @__PURE__ */ n(k, { size: "sm", variant: "ghost", icon: /* @__PURE__ */ n(Q, { size: 14 }), loading: h.busy, onClick: () => {
|
|
617
|
+
c.reload();
|
|
618
|
+
}, children: "Reload" })
|
|
619
|
+
] })
|
|
620
|
+
}
|
|
621
|
+
),
|
|
622
|
+
/* @__PURE__ */ u("div", { className: "mx-auto flex max-w-[1400px] flex-col gap-3 px-4 py-4 sm:px-5", children: [
|
|
623
|
+
o === !1 && /* @__PURE__ */ n(_, { tone: "info", children: "This server keeps no long-term memories (it needs `europacore serve --memory`)." }),
|
|
624
|
+
h.error && /* @__PURE__ */ n(_, { tone: "danger", action: /* @__PURE__ */ n(k, { size: "xs", onClick: () => {
|
|
625
|
+
c.open();
|
|
626
|
+
}, children: "Retry" }), children: h.error }),
|
|
627
|
+
a === "context" ? /* @__PURE__ */ n(De, { controller: c }) : h.busy && !h.records.length ? /* @__PURE__ */ n("div", { className: "flex justify-center py-16 text-accent", children: /* @__PURE__ */ n(K, {}) }) : /* @__PURE__ */ u("div", { className: "grid gap-4 lg:grid-cols-[220px_minmax(260px,360px)_1fr]", children: [
|
|
628
|
+
/* @__PURE__ */ n(Re, { nodes: p, selected: w.id, onSelect: b }),
|
|
629
|
+
/* @__PURE__ */ u("div", { className: "flex min-w-0 flex-col gap-2", children: [
|
|
630
|
+
/* @__PURE__ */ u("div", { className: "relative", children: [
|
|
631
|
+
/* @__PURE__ */ n(Z, { size: 14, className: "pointer-events-none absolute top-1/2 left-2.5 -translate-y-1/2 text-faint", "aria-hidden": "true" }),
|
|
632
|
+
/* @__PURE__ */ n(
|
|
633
|
+
"input",
|
|
634
|
+
{
|
|
635
|
+
type: "search",
|
|
636
|
+
value: l,
|
|
637
|
+
onChange: (d) => r({ q: d.target.value || null }),
|
|
638
|
+
placeholder: "Words, k:kind, s:source",
|
|
639
|
+
"aria-label": "Filter memories",
|
|
640
|
+
className: "h-8 w-full rounded-md border border-line bg-surface pr-2 pl-8 text-[13px] text-ink placeholder:text-faint focus:border-accent focus:ring-2 focus:ring-accent/20 focus:outline-none"
|
|
641
|
+
}
|
|
642
|
+
)
|
|
643
|
+
] }),
|
|
644
|
+
$.length ? /* @__PURE__ */ n("ul", { className: "flex flex-col gap-0.5", children: $.map((d) => /* @__PURE__ */ n("li", { children: /* @__PURE__ */ u(
|
|
645
|
+
"button",
|
|
646
|
+
{
|
|
647
|
+
type: "button",
|
|
648
|
+
onClick: () => r({ id: d.id }),
|
|
649
|
+
"aria-current": m?.id === d.id || void 0,
|
|
650
|
+
className: R(
|
|
651
|
+
"flex w-full flex-col gap-0.5 rounded-lg border px-3 py-2 text-left",
|
|
652
|
+
m?.id === d.id ? "border-accent bg-accent-soft" : "border-transparent hover:bg-surface-hover",
|
|
653
|
+
!y(d) && "opacity-70"
|
|
654
|
+
),
|
|
655
|
+
children: [
|
|
656
|
+
/* @__PURE__ */ n("span", { className: "truncate font-mono text-[12.5px] font-semibold text-ink", children: d.name }),
|
|
657
|
+
/* @__PURE__ */ n("span", { className: "truncate text-[12px] text-muted", children: C(d.description) }),
|
|
658
|
+
/* @__PURE__ */ u("span", { className: "flex flex-wrap items-center gap-1 text-[11px] text-faint", children: [
|
|
659
|
+
d.kind,
|
|
660
|
+
" · ",
|
|
661
|
+
d.source,
|
|
662
|
+
d.tokens ? ` · ${g(d.tokens.body)} tok` : "",
|
|
663
|
+
" · recalled ",
|
|
664
|
+
d.recall_count,
|
|
665
|
+
"×",
|
|
666
|
+
/* @__PURE__ */ n(G, { record: d })
|
|
667
|
+
] })
|
|
668
|
+
]
|
|
669
|
+
}
|
|
670
|
+
) }, d.id)) }) : /* @__PURE__ */ n("p", { className: "px-3 py-6 text-center text-[13px] text-muted", children: w.count === null ? "Loading…" : l ? `Nothing matches “${l}”.` : "Nothing here." })
|
|
671
|
+
] }),
|
|
672
|
+
/* @__PURE__ */ n("div", { className: "min-w-0 rounded-xl border border-line bg-surface p-4", children: m ? /* @__PURE__ */ n(ze, { controller: c, record: m }) : /* @__PURE__ */ n(X, { icon: /* @__PURE__ */ n(U, { size: 20 }), title: "Pick a memory", children: "Its text, when it loads, who wrote it and what is worth knowing about it show here." }) })
|
|
673
|
+
] })
|
|
674
|
+
] })
|
|
675
|
+
] });
|
|
676
|
+
}
|
|
677
|
+
export {
|
|
678
|
+
He as default
|
|
679
|
+
};
|