@dexto/tui 1.6.8 → 1.6.9

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.
Files changed (43) hide show
  1. package/dist/components/overlays/LoginOverlay.cjs +41 -50
  2. package/dist/components/overlays/LoginOverlay.d.ts.map +1 -1
  3. package/dist/components/overlays/LoginOverlay.js +43 -44
  4. package/dist/components/overlays/ModelSelectorRefactored.cjs +543 -221
  5. package/dist/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
  6. package/dist/components/overlays/ModelSelectorRefactored.js +553 -223
  7. package/dist/components/overlays/SessionSelectorRefactored.cjs +3 -0
  8. package/dist/components/overlays/SessionSelectorRefactored.d.ts.map +1 -1
  9. package/dist/components/overlays/SessionSelectorRefactored.js +3 -0
  10. package/dist/containers/OverlayContainer.cjs +35 -3
  11. package/dist/containers/OverlayContainer.d.ts.map +1 -1
  12. package/dist/containers/OverlayContainer.js +36 -3
  13. package/dist/hooks/useInputOrchestrator.cjs +1 -1
  14. package/dist/hooks/useInputOrchestrator.d.ts.map +1 -1
  15. package/dist/hooks/useInputOrchestrator.js +1 -1
  16. package/dist/host/index.cjs +12 -13
  17. package/dist/host/index.d.ts +23 -15
  18. package/dist/host/index.d.ts.map +1 -1
  19. package/dist/host/index.js +10 -11
  20. package/dist/index.d.cts +17 -12
  21. package/dist/interactive-commands/auth/index.d.ts +1 -1
  22. package/dist/interactive-commands/commands.cjs +2 -0
  23. package/dist/interactive-commands/commands.d.ts.map +1 -1
  24. package/dist/interactive-commands/commands.js +3 -1
  25. package/dist/interactive-commands/model/index.cjs +1 -1
  26. package/dist/interactive-commands/model/index.js +1 -1
  27. package/dist/interactive-commands/session/index.cjs +2 -0
  28. package/dist/interactive-commands/session/index.d.ts +2 -1
  29. package/dist/interactive-commands/session/index.d.ts.map +1 -1
  30. package/dist/interactive-commands/session/index.js +2 -1
  31. package/dist/interactive-commands/session/session-commands.cjs +26 -0
  32. package/dist/interactive-commands/session/session-commands.d.ts +5 -0
  33. package/dist/interactive-commands/session/session-commands.d.ts.map +1 -1
  34. package/dist/interactive-commands/session/session-commands.js +25 -0
  35. package/dist/utils/modelOrdering.cjs +106 -0
  36. package/dist/utils/modelOrdering.d.ts +7 -0
  37. package/dist/utils/modelOrdering.d.ts.map +1 -0
  38. package/dist/utils/modelOrdering.js +81 -0
  39. package/dist/utils/modelOrdering.test.cjs +59 -0
  40. package/dist/utils/modelOrdering.test.d.ts +2 -0
  41. package/dist/utils/modelOrdering.test.d.ts.map +1 -0
  42. package/dist/utils/modelOrdering.test.js +61 -0
  43. package/package.json +4 -4
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var session_commands_exports = {};
20
20
  __export(session_commands_exports, {
21
+ forkCommand: () => forkCommand,
21
22
  renameCommand: () => renameCommand,
22
23
  resumeCommand: () => resumeCommand,
23
24
  searchCommand: () => searchCommand
@@ -56,8 +57,33 @@ const renameCommand = {
56
57
  return true;
57
58
  }
58
59
  };
60
+ const forkCommand = {
61
+ name: "fork",
62
+ description: "Fork a session and create a child session with copied history",
63
+ usage: "/fork",
64
+ category: "General",
65
+ handler: async (_args, agent, ctx) => {
66
+ const parentSessionId = ctx.sessionId;
67
+ if (!parentSessionId) {
68
+ return ["\u274C No active session to fork.", "Start a session first, then run /fork."].join(
69
+ "\n"
70
+ );
71
+ }
72
+ const childSession = await agent.forkSession(parentSessionId);
73
+ const childMetadata = await agent.getSessionMetadata(childSession.id);
74
+ const title = childMetadata?.title ? ` (${childMetadata.title})` : "";
75
+ return [
76
+ "\u{1F374} Session forked",
77
+ `Parent: ${parentSessionId}`,
78
+ `Child: ${childSession.id}${title}`,
79
+ "",
80
+ "Use /resume to switch to the new session."
81
+ ].join("\n");
82
+ }
83
+ };
59
84
  // Annotate the CommonJS export names for ESM import in node:
60
85
  0 && (module.exports = {
86
+ forkCommand,
61
87
  renameCommand,
62
88
  resumeCommand,
63
89
  searchCommand
@@ -8,6 +8,7 @@
8
8
  * - resume: Shows interactive session selector
9
9
  * - search: Opens interactive search overlay
10
10
  * - rename: Rename the current session
11
+ * - fork: Fork the current session
11
12
  *
12
13
  * Note: For non-interactive session subcommands (list, history, delete),
13
14
  * see src/cli/commands/session-commands.ts
@@ -29,4 +30,8 @@ export declare const searchCommand: CommandDefinition;
29
30
  * The overlay is triggered via commandOverlays.ts registry.
30
31
  */
31
32
  export declare const renameCommand: CommandDefinition;
33
+ /**
34
+ * Fork command - creates a child session from the current session.
35
+ */
36
+ export declare const forkCommand: CommandDefinition;
32
37
  //# sourceMappingURL=session-commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-commands.d.ts","sourceRoot":"","sources":["../../../src/interactive-commands/session/session-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,sBAAsB,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,iBAqB3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,iBAc3B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,iBAa3B,CAAC"}
1
+ {"version":3,"file":"session-commands.d.ts","sourceRoot":"","sources":["../../../src/interactive-commands/session/session-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAkB,MAAM,sBAAsB,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,iBAqB3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,iBAc3B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,iBAa3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,iBA0BzB,CAAC"}
@@ -31,7 +31,32 @@ const renameCommand = {
31
31
  return true;
32
32
  }
33
33
  };
34
+ const forkCommand = {
35
+ name: "fork",
36
+ description: "Fork a session and create a child session with copied history",
37
+ usage: "/fork",
38
+ category: "General",
39
+ handler: async (_args, agent, ctx) => {
40
+ const parentSessionId = ctx.sessionId;
41
+ if (!parentSessionId) {
42
+ return ["\u274C No active session to fork.", "Start a session first, then run /fork."].join(
43
+ "\n"
44
+ );
45
+ }
46
+ const childSession = await agent.forkSession(parentSessionId);
47
+ const childMetadata = await agent.getSessionMetadata(childSession.id);
48
+ const title = childMetadata?.title ? ` (${childMetadata.title})` : "";
49
+ return [
50
+ "\u{1F374} Session forked",
51
+ `Parent: ${parentSessionId}`,
52
+ `Child: ${childSession.id}${title}`,
53
+ "",
54
+ "Use /resume to switch to the new session."
55
+ ].join("\n");
56
+ }
57
+ };
34
58
  export {
59
+ forkCommand,
35
60
  renameCommand,
36
61
  resumeCommand,
37
62
  searchCommand
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var modelOrdering_exports = {};
20
+ __export(modelOrdering_exports, {
21
+ compareModelsLatestFirst: () => compareModelsLatestFirst,
22
+ isDeprecatedModelStatus: () => isDeprecatedModelStatus
23
+ });
24
+ module.exports = __toCommonJS(modelOrdering_exports);
25
+ const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
26
+ const NUMBER_GROUP_PATTERN = /\d+/g;
27
+ const NAME_COLLATOR = new Intl.Collator("en", { numeric: true, sensitivity: "base" });
28
+ function parseIsoDateToTimestamp(value) {
29
+ const match = ISO_DATE_PATTERN.exec(value.trim());
30
+ if (!match) return null;
31
+ const year = Number(match[1]);
32
+ const month = Number(match[2]);
33
+ const day = Number(match[3]);
34
+ if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {
35
+ return null;
36
+ }
37
+ const timestamp = Date.UTC(year, month - 1, day);
38
+ const parsed = new Date(timestamp);
39
+ if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) {
40
+ return null;
41
+ }
42
+ return timestamp;
43
+ }
44
+ function stripDateTokens(name) {
45
+ return name.replace(/\d{4}-\d{2}-\d{2}/g, " ").replace(/\d{8}/g, " ").replace(/\s+/g, " ").trim();
46
+ }
47
+ function extractVersionPartsFromModelName(name) {
48
+ const modelTail = name.includes("/") ? name.slice(name.lastIndexOf("/") + 1) : name;
49
+ const normalized = stripDateTokens(modelTail.toLowerCase());
50
+ const parts = Array.from(normalized.matchAll(NUMBER_GROUP_PATTERN)).map((match) => {
51
+ const raw = match[0];
52
+ if (!raw) return null;
53
+ if (raw.length >= 6) return null;
54
+ const parsed = Number(raw);
55
+ return Number.isFinite(parsed) ? parsed : null;
56
+ }).filter((part) => part !== null);
57
+ return parts;
58
+ }
59
+ function compareVersionPartsDescending(left, right) {
60
+ const maxParts = Math.max(left.length, right.length);
61
+ for (let i = 0; i < maxParts; i++) {
62
+ const leftPart = left[i];
63
+ const rightPart = right[i];
64
+ if (leftPart === void 0 && rightPart === void 0) {
65
+ continue;
66
+ }
67
+ if (leftPart === void 0) {
68
+ return 1;
69
+ }
70
+ if (rightPart === void 0) {
71
+ return -1;
72
+ }
73
+ if (leftPart !== rightPart) {
74
+ return rightPart - leftPart;
75
+ }
76
+ }
77
+ return 0;
78
+ }
79
+ function compareModelsLatestFirst(left, right) {
80
+ const leftDate = left.releaseDate ? parseIsoDateToTimestamp(left.releaseDate) : null;
81
+ const rightDate = right.releaseDate ? parseIsoDateToTimestamp(right.releaseDate) : null;
82
+ if (leftDate !== null && rightDate !== null && leftDate !== rightDate) {
83
+ return rightDate - leftDate;
84
+ }
85
+ if (leftDate !== null && rightDate === null) {
86
+ return -1;
87
+ }
88
+ if (leftDate === null && rightDate !== null) {
89
+ return 1;
90
+ }
91
+ const leftVersion = extractVersionPartsFromModelName(left.name);
92
+ const rightVersion = extractVersionPartsFromModelName(right.name);
93
+ const byVersion = compareVersionPartsDescending(leftVersion, rightVersion);
94
+ if (byVersion !== 0) {
95
+ return byVersion;
96
+ }
97
+ return NAME_COLLATOR.compare(right.name, left.name);
98
+ }
99
+ function isDeprecatedModelStatus(status) {
100
+ return status?.toLowerCase() === "deprecated";
101
+ }
102
+ // Annotate the CommonJS export names for ESM import in node:
103
+ 0 && (module.exports = {
104
+ compareModelsLatestFirst,
105
+ isDeprecatedModelStatus
106
+ });
@@ -0,0 +1,7 @@
1
+ export interface ModelRecencyCandidate {
2
+ name: string;
3
+ releaseDate?: string;
4
+ }
5
+ export declare function compareModelsLatestFirst(left: ModelRecencyCandidate, right: ModelRecencyCandidate): number;
6
+ export declare function isDeprecatedModelStatus(status: string | undefined): boolean;
7
+ //# sourceMappingURL=modelOrdering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelOrdering.d.ts","sourceRoot":"","sources":["../../src/utils/modelOrdering.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AA8ED,wBAAgB,wBAAwB,CACpC,IAAI,EAAE,qBAAqB,EAC3B,KAAK,EAAE,qBAAqB,GAC7B,MAAM,CA0BR;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAE3E"}
@@ -0,0 +1,81 @@
1
+ const ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
2
+ const NUMBER_GROUP_PATTERN = /\d+/g;
3
+ const NAME_COLLATOR = new Intl.Collator("en", { numeric: true, sensitivity: "base" });
4
+ function parseIsoDateToTimestamp(value) {
5
+ const match = ISO_DATE_PATTERN.exec(value.trim());
6
+ if (!match) return null;
7
+ const year = Number(match[1]);
8
+ const month = Number(match[2]);
9
+ const day = Number(match[3]);
10
+ if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {
11
+ return null;
12
+ }
13
+ const timestamp = Date.UTC(year, month - 1, day);
14
+ const parsed = new Date(timestamp);
15
+ if (parsed.getUTCFullYear() !== year || parsed.getUTCMonth() !== month - 1 || parsed.getUTCDate() !== day) {
16
+ return null;
17
+ }
18
+ return timestamp;
19
+ }
20
+ function stripDateTokens(name) {
21
+ return name.replace(/\d{4}-\d{2}-\d{2}/g, " ").replace(/\d{8}/g, " ").replace(/\s+/g, " ").trim();
22
+ }
23
+ function extractVersionPartsFromModelName(name) {
24
+ const modelTail = name.includes("/") ? name.slice(name.lastIndexOf("/") + 1) : name;
25
+ const normalized = stripDateTokens(modelTail.toLowerCase());
26
+ const parts = Array.from(normalized.matchAll(NUMBER_GROUP_PATTERN)).map((match) => {
27
+ const raw = match[0];
28
+ if (!raw) return null;
29
+ if (raw.length >= 6) return null;
30
+ const parsed = Number(raw);
31
+ return Number.isFinite(parsed) ? parsed : null;
32
+ }).filter((part) => part !== null);
33
+ return parts;
34
+ }
35
+ function compareVersionPartsDescending(left, right) {
36
+ const maxParts = Math.max(left.length, right.length);
37
+ for (let i = 0; i < maxParts; i++) {
38
+ const leftPart = left[i];
39
+ const rightPart = right[i];
40
+ if (leftPart === void 0 && rightPart === void 0) {
41
+ continue;
42
+ }
43
+ if (leftPart === void 0) {
44
+ return 1;
45
+ }
46
+ if (rightPart === void 0) {
47
+ return -1;
48
+ }
49
+ if (leftPart !== rightPart) {
50
+ return rightPart - leftPart;
51
+ }
52
+ }
53
+ return 0;
54
+ }
55
+ function compareModelsLatestFirst(left, right) {
56
+ const leftDate = left.releaseDate ? parseIsoDateToTimestamp(left.releaseDate) : null;
57
+ const rightDate = right.releaseDate ? parseIsoDateToTimestamp(right.releaseDate) : null;
58
+ if (leftDate !== null && rightDate !== null && leftDate !== rightDate) {
59
+ return rightDate - leftDate;
60
+ }
61
+ if (leftDate !== null && rightDate === null) {
62
+ return -1;
63
+ }
64
+ if (leftDate === null && rightDate !== null) {
65
+ return 1;
66
+ }
67
+ const leftVersion = extractVersionPartsFromModelName(left.name);
68
+ const rightVersion = extractVersionPartsFromModelName(right.name);
69
+ const byVersion = compareVersionPartsDescending(leftVersion, rightVersion);
70
+ if (byVersion !== 0) {
71
+ return byVersion;
72
+ }
73
+ return NAME_COLLATOR.compare(right.name, left.name);
74
+ }
75
+ function isDeprecatedModelStatus(status) {
76
+ return status?.toLowerCase() === "deprecated";
77
+ }
78
+ export {
79
+ compareModelsLatestFirst,
80
+ isDeprecatedModelStatus
81
+ };
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var import_vitest = require("vitest");
3
+ var import_modelOrdering = require("./modelOrdering.js");
4
+ function sortModels(models) {
5
+ return [...models].sort(import_modelOrdering.compareModelsLatestFirst).map((model) => model.name);
6
+ }
7
+ (0, import_vitest.describe)("compareModelsLatestFirst", () => {
8
+ (0, import_vitest.it)("prioritizes releaseDate over version-like tokens in model names", () => {
9
+ const sorted = sortModels([
10
+ { name: "gpt-oss-120b" },
11
+ { name: "gpt-5.2", releaseDate: "2026-02-05" },
12
+ { name: "gpt-5.1", releaseDate: "2025-12-11" }
13
+ ]);
14
+ (0, import_vitest.expect)(sorted).toEqual(["gpt-5.2", "gpt-5.1", "gpt-oss-120b"]);
15
+ });
16
+ (0, import_vitest.it)("sorts by releaseDate descending when available", () => {
17
+ const sorted = sortModels([
18
+ { name: "gpt-4", releaseDate: "2023-11-06" },
19
+ { name: "gpt-5", releaseDate: "2025-08-07" },
20
+ { name: "gpt-4o", releaseDate: "2024-05-13" }
21
+ ]);
22
+ (0, import_vitest.expect)(sorted).toEqual(["gpt-5", "gpt-4o", "gpt-4"]);
23
+ });
24
+ (0, import_vitest.it)("keeps dated models ahead of undated models", () => {
25
+ const sorted = sortModels([
26
+ { name: "gpt-4.1" },
27
+ { name: "gpt-5.1", releaseDate: "2025-12-11" },
28
+ { name: "gpt-5.2", releaseDate: "2026-02-05" }
29
+ ]);
30
+ (0, import_vitest.expect)(sorted).toEqual(["gpt-5.2", "gpt-5.1", "gpt-4.1"]);
31
+ });
32
+ (0, import_vitest.it)("falls back to numeric-aware version ordering when release dates tie", () => {
33
+ const sorted = sortModels([
34
+ { name: "gpt-5.1", releaseDate: "2025-08-01" },
35
+ { name: "gpt-5.2", releaseDate: "2025-08-01" },
36
+ { name: "gpt-5.10", releaseDate: "2025-08-01" }
37
+ ]);
38
+ (0, import_vitest.expect)(sorted).toEqual(["gpt-5.10", "gpt-5.2", "gpt-5.1"]);
39
+ });
40
+ (0, import_vitest.it)("falls back to numeric-aware ordering for undated models", () => {
41
+ const sorted = sortModels([
42
+ { name: "minimax-m2" },
43
+ { name: "minimax-m2.5" },
44
+ { name: "minimax-m2.1" }
45
+ ]);
46
+ (0, import_vitest.expect)(sorted).toEqual(["minimax-m2.5", "minimax-m2.1", "minimax-m2"]);
47
+ });
48
+ });
49
+ (0, import_vitest.describe)("isDeprecatedModelStatus", () => {
50
+ (0, import_vitest.it)("returns true for deprecated status", () => {
51
+ (0, import_vitest.expect)((0, import_modelOrdering.isDeprecatedModelStatus)("deprecated")).toBe(true);
52
+ (0, import_vitest.expect)((0, import_modelOrdering.isDeprecatedModelStatus)("DEPRECATED")).toBe(true);
53
+ });
54
+ (0, import_vitest.it)("returns false for undefined or non-deprecated status", () => {
55
+ (0, import_vitest.expect)((0, import_modelOrdering.isDeprecatedModelStatus)(void 0)).toBe(false);
56
+ (0, import_vitest.expect)((0, import_modelOrdering.isDeprecatedModelStatus)("active")).toBe(false);
57
+ (0, import_vitest.expect)((0, import_modelOrdering.isDeprecatedModelStatus)("preview")).toBe(false);
58
+ });
59
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=modelOrdering.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modelOrdering.test.d.ts","sourceRoot":"","sources":["../../src/utils/modelOrdering.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,61 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ compareModelsLatestFirst,
4
+ isDeprecatedModelStatus
5
+ } from "./modelOrdering.js";
6
+ function sortModels(models) {
7
+ return [...models].sort(compareModelsLatestFirst).map((model) => model.name);
8
+ }
9
+ describe("compareModelsLatestFirst", () => {
10
+ it("prioritizes releaseDate over version-like tokens in model names", () => {
11
+ const sorted = sortModels([
12
+ { name: "gpt-oss-120b" },
13
+ { name: "gpt-5.2", releaseDate: "2026-02-05" },
14
+ { name: "gpt-5.1", releaseDate: "2025-12-11" }
15
+ ]);
16
+ expect(sorted).toEqual(["gpt-5.2", "gpt-5.1", "gpt-oss-120b"]);
17
+ });
18
+ it("sorts by releaseDate descending when available", () => {
19
+ const sorted = sortModels([
20
+ { name: "gpt-4", releaseDate: "2023-11-06" },
21
+ { name: "gpt-5", releaseDate: "2025-08-07" },
22
+ { name: "gpt-4o", releaseDate: "2024-05-13" }
23
+ ]);
24
+ expect(sorted).toEqual(["gpt-5", "gpt-4o", "gpt-4"]);
25
+ });
26
+ it("keeps dated models ahead of undated models", () => {
27
+ const sorted = sortModels([
28
+ { name: "gpt-4.1" },
29
+ { name: "gpt-5.1", releaseDate: "2025-12-11" },
30
+ { name: "gpt-5.2", releaseDate: "2026-02-05" }
31
+ ]);
32
+ expect(sorted).toEqual(["gpt-5.2", "gpt-5.1", "gpt-4.1"]);
33
+ });
34
+ it("falls back to numeric-aware version ordering when release dates tie", () => {
35
+ const sorted = sortModels([
36
+ { name: "gpt-5.1", releaseDate: "2025-08-01" },
37
+ { name: "gpt-5.2", releaseDate: "2025-08-01" },
38
+ { name: "gpt-5.10", releaseDate: "2025-08-01" }
39
+ ]);
40
+ expect(sorted).toEqual(["gpt-5.10", "gpt-5.2", "gpt-5.1"]);
41
+ });
42
+ it("falls back to numeric-aware ordering for undated models", () => {
43
+ const sorted = sortModels([
44
+ { name: "minimax-m2" },
45
+ { name: "minimax-m2.5" },
46
+ { name: "minimax-m2.1" }
47
+ ]);
48
+ expect(sorted).toEqual(["minimax-m2.5", "minimax-m2.1", "minimax-m2"]);
49
+ });
50
+ });
51
+ describe("isDeprecatedModelStatus", () => {
52
+ it("returns true for deprecated status", () => {
53
+ expect(isDeprecatedModelStatus("deprecated")).toBe(true);
54
+ expect(isDeprecatedModelStatus("DEPRECATED")).toBe(true);
55
+ });
56
+ it("returns false for undefined or non-deprecated status", () => {
57
+ expect(isDeprecatedModelStatus(void 0)).toBe(false);
58
+ expect(isDeprecatedModelStatus("active")).toBe(false);
59
+ expect(isDeprecatedModelStatus("preview")).toBe(false);
60
+ });
61
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexto/tui",
3
- "version": "1.6.8",
3
+ "version": "1.6.9",
4
4
  "description": "Interactive terminal UI for Dexto CLI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -28,9 +28,9 @@
28
28
  "string-width": "^8.1.0",
29
29
  "strip-ansi": "^7.1.2",
30
30
  "wrap-ansi": "^9.0.2",
31
- "@dexto/agent-management": "1.6.8",
32
- "@dexto/core": "1.6.8",
33
- "@dexto/registry": "1.6.8"
31
+ "@dexto/registry": "1.6.9",
32
+ "@dexto/agent-management": "1.6.9",
33
+ "@dexto/core": "1.6.9"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/react": "^19.0.0",