@agentprojectcontext/apx 1.48.2 → 1.49.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/package.json +1 -1
- package/src/host/daemon/api/sessions.js +11 -2
- package/src/interfaces/cli/commands/sessions.js +25 -15
- package/src/interfaces/web/dist/assets/index-lu6lfr1N.js +656 -0
- package/src/interfaces/web/dist/assets/{index-Bgu-xy_L.js.map → index-lu6lfr1N.js.map} +1 -1
- package/src/interfaces/web/dist/index.html +1 -1
- package/src/interfaces/web/src/components/RobyBubble.tsx +15 -0
- package/src/interfaces/web/src/i18n/en.ts +16 -0
- package/src/interfaces/web/src/i18n/es.ts +16 -0
- package/src/interfaces/web/src/lib/api/sessions.ts +10 -5
- package/src/interfaces/web/src/screens/base/SessionsTab.tsx +115 -25
- package/src/interfaces/web/dist/assets/index-Bgu-xy_L.js +0 -656
package/package.json
CHANGED
|
@@ -12,22 +12,31 @@ import {
|
|
|
12
12
|
agentSessionsDir,
|
|
13
13
|
createAgentSessionFile,
|
|
14
14
|
} from "#core/stores/sessions.js";
|
|
15
|
-
import { collectAllSessions } from "#interfaces/cli/commands/sessions.js";
|
|
15
|
+
import { collectAllSessions, filterSessionsByQuery } from "#interfaces/cli/commands/sessions.js";
|
|
16
16
|
import { pageEnvelope } from "./shared.js";
|
|
17
17
|
|
|
18
18
|
export function register(app, { projects, project }) {
|
|
19
19
|
// Cross-engine sessions (apx · claude · codex), newest first. Returns a
|
|
20
20
|
// { meta, data } envelope (meta = pagination info, data = rows). Paginated
|
|
21
21
|
// via ?limit & ?offset; with no limit, data is the full set as one page.
|
|
22
|
+
// Optional ?q= filters via the same core as `apx session find` (title match,
|
|
23
|
+
// + transcript content when ?deep=1) so terminal and web search are identical.
|
|
22
24
|
app.get("/sessions", (req, res) => {
|
|
23
25
|
const engineId = req.query.engine ? String(req.query.engine) : null;
|
|
26
|
+
const q = req.query.q ? String(req.query.q) : "";
|
|
27
|
+
const deep = req.query.deep === "1" || req.query.deep === "true";
|
|
24
28
|
let rows = [];
|
|
25
29
|
try {
|
|
26
30
|
rows = collectAllSessions({}, { engineId });
|
|
27
31
|
} catch (e) {
|
|
28
32
|
return res.status(500).json({ error: e.message, meta: { total: 0, offset: 0, limit: null, pageSize: 0, page: 1, pageCount: 1 }, data: [] });
|
|
29
33
|
}
|
|
30
|
-
|
|
34
|
+
if (q.trim()) {
|
|
35
|
+
// filterSessionsByQuery already de-dupes and sorts newest-first.
|
|
36
|
+
rows = filterSessionsByQuery(rows, { query: q, deep });
|
|
37
|
+
} else {
|
|
38
|
+
rows.sort((a, b) => (b.mtime || 0) - (a.mtime || 0));
|
|
39
|
+
}
|
|
31
40
|
res.json(pageEnvelope(rows, req.query));
|
|
32
41
|
});
|
|
33
42
|
|
|
@@ -774,6 +774,30 @@ function sessionContainsText(row, needle) {
|
|
|
774
774
|
return text.toLowerCase().includes(needle);
|
|
775
775
|
}
|
|
776
776
|
|
|
777
|
+
// Filter collected session rows by a free-text query. Always matches the
|
|
778
|
+
// title; with deep=true also scans transcript content (slower). De-dupes by
|
|
779
|
+
// engine:id and returns full rows + a `match` field ("title"|"content"),
|
|
780
|
+
// newest first. Shared core for the CLI (apx session find) and the daemon
|
|
781
|
+
// (GET /sessions?q=…) so terminal and web search behave identically.
|
|
782
|
+
export function filterSessionsByQuery(rows, { query, deep = false, limit = 0 } = {}) {
|
|
783
|
+
const needle = String(query || "").trim().toLowerCase();
|
|
784
|
+
if (!needle) return [];
|
|
785
|
+
const seen = new Set();
|
|
786
|
+
const matches = [];
|
|
787
|
+
for (const row of rows) {
|
|
788
|
+
const titleHit = String(row.title).toLowerCase().includes(needle);
|
|
789
|
+
let where = titleHit ? "title" : null;
|
|
790
|
+
if (!titleHit && deep && sessionContainsText(row, needle)) where = "content";
|
|
791
|
+
if (!where) continue;
|
|
792
|
+
const key = `${row.engine}:${row.id}`;
|
|
793
|
+
if (seen.has(key)) continue;
|
|
794
|
+
seen.add(key);
|
|
795
|
+
matches.push({ ...row, match: where });
|
|
796
|
+
}
|
|
797
|
+
matches.sort((a, b) => b.mtime - a.mtime);
|
|
798
|
+
return limit > 0 ? matches.slice(0, limit) : matches;
|
|
799
|
+
}
|
|
800
|
+
|
|
777
801
|
export function cmdSessionFind(args, opts = {}) {
|
|
778
802
|
const query = (args._ || []).join(" ").trim();
|
|
779
803
|
if (!query) {
|
|
@@ -781,7 +805,6 @@ export function cmdSessionFind(args, opts = {}) {
|
|
|
781
805
|
'apx session find: missing search text — e.g. apx session find "mejorar interfaz web"'
|
|
782
806
|
);
|
|
783
807
|
}
|
|
784
|
-
const needle = query.toLowerCase();
|
|
785
808
|
const deep = !!(args.flags.deep || args.flags.content);
|
|
786
809
|
const asJson = !!args.flags.json;
|
|
787
810
|
const engineFlag =
|
|
@@ -799,20 +822,7 @@ export function cmdSessionFind(args, opts = {}) {
|
|
|
799
822
|
|
|
800
823
|
const dir = resolveTargetDir(args, opts);
|
|
801
824
|
const rows = collectAllSessions(opts, { dir, engineId: engineFlag });
|
|
802
|
-
|
|
803
|
-
const seen = new Set();
|
|
804
|
-
const matches = [];
|
|
805
|
-
for (const row of rows) {
|
|
806
|
-
const titleHit = String(row.title).toLowerCase().includes(needle);
|
|
807
|
-
let where = titleHit ? "title" : null;
|
|
808
|
-
if (!titleHit && deep && sessionContainsText(row, needle)) where = "content";
|
|
809
|
-
if (!where) continue;
|
|
810
|
-
const key = `${row.engine}:${row.id}`;
|
|
811
|
-
if (seen.has(key)) continue;
|
|
812
|
-
seen.add(key);
|
|
813
|
-
matches.push({ ...row, match: where });
|
|
814
|
-
}
|
|
815
|
-
matches.sort((a, b) => b.mtime - a.mtime);
|
|
825
|
+
const matches = filterSessionsByQuery(rows, { query, deep });
|
|
816
826
|
const shown = matches.slice(0, limit);
|
|
817
827
|
|
|
818
828
|
if (asJson) {
|