@stigmer/react 3.5.0 → 3.5.1
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 +4 -4
- package/session/useSessionExecutions.d.ts +14 -0
- package/session/useSessionExecutions.d.ts.map +1 -1
- package/session/useSessionExecutions.js +27 -1
- package/session/useSessionExecutions.js.map +1 -1
- package/src/session/__tests__/useSessionExecutions.test.ts +63 -0
- package/src/session/useSessionExecutions.ts +27 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stigmer/react",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.1",
|
|
4
4
|
"description": "React provider and client hook for the Stigmer platform SDK",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@bufbuild/protovalidate": "^1.1.1",
|
|
39
39
|
"@dagrejs/dagre": "^1.1.4",
|
|
40
|
-
"@stigmer/theme": "3.5.
|
|
40
|
+
"@stigmer/theme": "3.5.1",
|
|
41
41
|
"diff": "^8.0.3",
|
|
42
42
|
"fflate": "^0.8.2",
|
|
43
43
|
"hast-util-to-jsx-runtime": "^2.3.6",
|
|
@@ -60,8 +60,8 @@
|
|
|
60
60
|
"@codemirror/state": "^6.0.0",
|
|
61
61
|
"@codemirror/view": "^6.0.0",
|
|
62
62
|
"@lezer/highlight": "^1.0.0",
|
|
63
|
-
"@stigmer/protos": "3.5.
|
|
64
|
-
"@stigmer/sdk": "3.5.
|
|
63
|
+
"@stigmer/protos": "3.5.1",
|
|
64
|
+
"@stigmer/sdk": "3.5.1",
|
|
65
65
|
"@tanstack/react-table": "^8.20.0",
|
|
66
66
|
"@xyflow/react": "^12.0.0",
|
|
67
67
|
"elkjs": "^0.9.0",
|
|
@@ -62,5 +62,19 @@ export interface UseSessionExecutionsReturn {
|
|
|
62
62
|
* const { executions } = useSessionExecutions(sessionId ?? null);
|
|
63
63
|
* ```
|
|
64
64
|
*/
|
|
65
|
+
/**
|
|
66
|
+
* Returns the executions in chronological (oldest-first) order — the order
|
|
67
|
+
* the conversation thread renders top-to-bottom.
|
|
68
|
+
*
|
|
69
|
+
* Defense-in-depth against an unordered list response: the executions ARE the
|
|
70
|
+
* transcript, so a scrambled order drops the newest turns out of view (they no
|
|
71
|
+
* longer sort to the bottom). The server orders this list, but the thread must
|
|
72
|
+
* never depend on that alone. Resource ids are time-sortable ULIDs
|
|
73
|
+
* (`aex_01k…`), so an ascending id sort is creation order without parsing
|
|
74
|
+
* timestamps; entries missing an id sort last but keep a stable relative order.
|
|
75
|
+
*
|
|
76
|
+
* @internal Exported for testing — not part of the public API.
|
|
77
|
+
*/
|
|
78
|
+
export declare function sortChronologically(executions: readonly AgentExecution[]): AgentExecution[];
|
|
65
79
|
export declare function useSessionExecutions(sessionId: string | null, options?: UseSessionExecutionsOptions): UseSessionExecutionsReturn;
|
|
66
80
|
//# sourceMappingURL=useSessionExecutions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSessionExecutions.d.ts","sourceRoot":"","sources":["../../src/session/useSessionExecutions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;AAKlG,gDAAgD;AAChD,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,oDAAoD;AACpD,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,CAAC,EAAE,2BAA2B,GACpC,0BAA0B,CAyB5B"}
|
|
1
|
+
{"version":3,"file":"useSessionExecutions.d.ts","sourceRoot":"","sources":["../../src/session/useSessionExecutions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;AAKlG,gDAAgD;AAChD,MAAM,WAAW,2BAA2B;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,oDAAoD;AACpD,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;IAC/C,mDAAmD;IACnD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,sDAAsD;IACtD,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,SAAS,cAAc,EAAE,GACpC,cAAc,EAAE,CASlB;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,CAAC,EAAE,2BAA2B,GACpC,0BAA0B,CAyB5B"}
|
|
@@ -37,6 +37,32 @@ import { useFetch } from "../internal/useFetch.js";
|
|
|
37
37
|
* const { executions } = useSessionExecutions(sessionId ?? null);
|
|
38
38
|
* ```
|
|
39
39
|
*/
|
|
40
|
+
/**
|
|
41
|
+
* Returns the executions in chronological (oldest-first) order — the order
|
|
42
|
+
* the conversation thread renders top-to-bottom.
|
|
43
|
+
*
|
|
44
|
+
* Defense-in-depth against an unordered list response: the executions ARE the
|
|
45
|
+
* transcript, so a scrambled order drops the newest turns out of view (they no
|
|
46
|
+
* longer sort to the bottom). The server orders this list, but the thread must
|
|
47
|
+
* never depend on that alone. Resource ids are time-sortable ULIDs
|
|
48
|
+
* (`aex_01k…`), so an ascending id sort is creation order without parsing
|
|
49
|
+
* timestamps; entries missing an id sort last but keep a stable relative order.
|
|
50
|
+
*
|
|
51
|
+
* @internal Exported for testing — not part of the public API.
|
|
52
|
+
*/
|
|
53
|
+
export function sortChronologically(executions) {
|
|
54
|
+
return [...executions].sort((a, b) => {
|
|
55
|
+
const aId = a.metadata?.id ?? "";
|
|
56
|
+
const bId = b.metadata?.id ?? "";
|
|
57
|
+
if (aId === bId)
|
|
58
|
+
return 0;
|
|
59
|
+
if (!aId)
|
|
60
|
+
return 1;
|
|
61
|
+
if (!bId)
|
|
62
|
+
return -1;
|
|
63
|
+
return aId < bId ? -1 : 1;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
40
66
|
export function useSessionExecutions(sessionId, options) {
|
|
41
67
|
const stigmer = useStigmer();
|
|
42
68
|
const { data: executions, isLoading, isRefetching, error, refetch } = useFetch(sessionId
|
|
@@ -45,7 +71,7 @@ export function useSessionExecutions(sessionId, options) {
|
|
|
45
71
|
sessionId,
|
|
46
72
|
pageSize: 100,
|
|
47
73
|
}))
|
|
48
|
-
.then((result) => result.entries)
|
|
74
|
+
.then((result) => sortChronologically(result.entries))
|
|
49
75
|
: null, [sessionId, stigmer], [], {
|
|
50
76
|
cacheKey: sessionId ? `session-executions:${sessionId}` : undefined,
|
|
51
77
|
refetchInterval: options?.refetchInterval,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSessionExecutions.js","sourceRoot":"","sources":["../../src/session/useSessionExecutions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,yCAAyC,EAAE,MAAM,4DAA4D,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAiCnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAAwB,EACxB,OAAqC;IAErC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,CAC5E,SAAS;QACP,CAAC,CAAC,GAAG,EAAE,CACH,OAAO,CAAC,cAAc;aACnB,aAAa,CACZ,MAAM,CAAC,yCAAyC,EAAE;YAChD,SAAS;YACT,QAAQ,EAAE,GAAG;SACd,CAAC,CACH;aACA,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useSessionExecutions.js","sourceRoot":"","sources":["../../src/session/useSessionExecutions.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,OAAO,EAAE,yCAAyC,EAAE,MAAM,4DAA4D,CAAC;AACvH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAiCnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAqC;IAErC,OAAO,CAAC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACnC,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC;QACjC,IAAI,GAAG,KAAK,GAAG;YAAE,OAAO,CAAC,CAAC;QAC1B,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,CAAC;QACnB,IAAI,CAAC,GAAG;YAAE,OAAO,CAAC,CAAC,CAAC;QACpB,OAAO,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,SAAwB,EACxB,OAAqC;IAErC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,QAAQ,CAC5E,SAAS;QACP,CAAC,CAAC,GAAG,EAAE,CACH,OAAO,CAAC,cAAc;aACnB,aAAa,CACZ,MAAM,CAAC,yCAAyC,EAAE;YAChD,SAAS;YACT,QAAQ,EAAE,GAAG;SACd,CAAC,CACH;aACA,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5D,CAAC,CAAC,IAAI,EACR,CAAC,SAAS,EAAE,OAAO,CAAC,EACpB,EAAsB,EACtB;QACE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC,sBAAsB,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS;QACnE,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,oBAAoB,EAAE,OAAO,EAAE,oBAAoB;KACpD,CACF,CAAC;IAEF,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { create } from "@bufbuild/protobuf";
|
|
3
|
+
import {
|
|
4
|
+
AgentExecutionSchema,
|
|
5
|
+
type AgentExecution,
|
|
6
|
+
} from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
|
|
7
|
+
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
8
|
+
import { sortChronologically } from "../useSessionExecutions";
|
|
9
|
+
|
|
10
|
+
function exec(id: string): AgentExecution {
|
|
11
|
+
const e = create(AgentExecutionSchema);
|
|
12
|
+
const metadata = create(ApiResourceMetadataSchema);
|
|
13
|
+
metadata.id = id;
|
|
14
|
+
e.metadata = metadata;
|
|
15
|
+
return e;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function ids(list: readonly AgentExecution[]): string[] {
|
|
19
|
+
return list.map((e) => e.metadata?.id ?? "");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
describe("sortChronologically", () => {
|
|
23
|
+
it("orders executions oldest-first by their ULID id", () => {
|
|
24
|
+
// Real ids from the pilot session, returned by the server in scrambled
|
|
25
|
+
// heap order — the afternoon turns (…vk…) interleaved with the evening
|
|
26
|
+
// turns (…w3…/…w4…). Chronological order is ascending ULID.
|
|
27
|
+
const scrambled = [
|
|
28
|
+
exec("aex_01kyw3zeq8cre6cc8gznf31y13"),
|
|
29
|
+
exec("aex_01kyvk1hxyrhch1q23p5j177pb"),
|
|
30
|
+
exec("aex_01kyw416w9mg6ezzpkc6q9y71x"),
|
|
31
|
+
exec("aex_01kyvk2sh0vjc69c7z3q4c9r1m"),
|
|
32
|
+
exec("aex_01kyw45qkf88x28pf9bxmrr3bf"),
|
|
33
|
+
exec("aex_01kyw3y0rfx9vd7dhnawgqgnb0"),
|
|
34
|
+
exec("aex_01kyvk3v34vh9phedx2ezajxtr"),
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
expect(ids(sortChronologically(scrambled))).toEqual([
|
|
38
|
+
"aex_01kyvk1hxyrhch1q23p5j177pb",
|
|
39
|
+
"aex_01kyvk2sh0vjc69c7z3q4c9r1m",
|
|
40
|
+
"aex_01kyvk3v34vh9phedx2ezajxtr",
|
|
41
|
+
"aex_01kyw3y0rfx9vd7dhnawgqgnb0",
|
|
42
|
+
"aex_01kyw3zeq8cre6cc8gznf31y13",
|
|
43
|
+
"aex_01kyw416w9mg6ezzpkc6q9y71x",
|
|
44
|
+
"aex_01kyw45qkf88x28pf9bxmrr3bf",
|
|
45
|
+
]);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("does not mutate the input array", () => {
|
|
49
|
+
const input = [exec("aex_02"), exec("aex_01")];
|
|
50
|
+
const before = ids(input);
|
|
51
|
+
sortChronologically(input);
|
|
52
|
+
expect(ids(input)).toEqual(before);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("sorts entries missing an id last", () => {
|
|
56
|
+
const list = [exec("aex_02"), exec(""), exec("aex_01")];
|
|
57
|
+
expect(ids(sortChronologically(list))).toEqual(["aex_01", "aex_02", ""]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("returns an empty array unchanged", () => {
|
|
61
|
+
expect(sortChronologically([])).toEqual([]);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -71,6 +71,32 @@ export interface UseSessionExecutionsReturn {
|
|
|
71
71
|
* const { executions } = useSessionExecutions(sessionId ?? null);
|
|
72
72
|
* ```
|
|
73
73
|
*/
|
|
74
|
+
/**
|
|
75
|
+
* Returns the executions in chronological (oldest-first) order — the order
|
|
76
|
+
* the conversation thread renders top-to-bottom.
|
|
77
|
+
*
|
|
78
|
+
* Defense-in-depth against an unordered list response: the executions ARE the
|
|
79
|
+
* transcript, so a scrambled order drops the newest turns out of view (they no
|
|
80
|
+
* longer sort to the bottom). The server orders this list, but the thread must
|
|
81
|
+
* never depend on that alone. Resource ids are time-sortable ULIDs
|
|
82
|
+
* (`aex_01k…`), so an ascending id sort is creation order without parsing
|
|
83
|
+
* timestamps; entries missing an id sort last but keep a stable relative order.
|
|
84
|
+
*
|
|
85
|
+
* @internal Exported for testing — not part of the public API.
|
|
86
|
+
*/
|
|
87
|
+
export function sortChronologically(
|
|
88
|
+
executions: readonly AgentExecution[],
|
|
89
|
+
): AgentExecution[] {
|
|
90
|
+
return [...executions].sort((a, b) => {
|
|
91
|
+
const aId = a.metadata?.id ?? "";
|
|
92
|
+
const bId = b.metadata?.id ?? "";
|
|
93
|
+
if (aId === bId) return 0;
|
|
94
|
+
if (!aId) return 1;
|
|
95
|
+
if (!bId) return -1;
|
|
96
|
+
return aId < bId ? -1 : 1;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
74
100
|
export function useSessionExecutions(
|
|
75
101
|
sessionId: string | null,
|
|
76
102
|
options?: UseSessionExecutionsOptions,
|
|
@@ -87,7 +113,7 @@ export function useSessionExecutions(
|
|
|
87
113
|
pageSize: 100,
|
|
88
114
|
}),
|
|
89
115
|
)
|
|
90
|
-
.then((result) => result.entries)
|
|
116
|
+
.then((result) => sortChronologically(result.entries))
|
|
91
117
|
: null,
|
|
92
118
|
[sessionId, stigmer],
|
|
93
119
|
[] as AgentExecution[],
|