pi-llama-cpp 0.10.0 → 0.12.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 +187 -10
- package/package.json +6 -6
- package/src/api/client.ts +76 -32
- package/src/constants.ts +15 -0
- package/src/index.ts +3 -5
- package/src/interfaces/events.ts +14 -3
- package/src/interfaces/server.ts +27 -0
- package/src/interfaces/settings.ts +76 -2
- package/src/managers/command.ts +369 -50
- package/src/managers/events.ts +28 -10
- package/src/managers/server.ts +90 -16
- package/src/managers/settings.ts +181 -44
- package/src/models/baseModel.ts +37 -15
- package/src/models/routerModel.ts +2 -1
- package/src/server.ts +103 -28
- package/src/sse/client.ts +28 -16
- package/src/sse/manager.ts +26 -13
- package/src/ui/dialog.ts +287 -0
- package/src/ui/overrideEntryEditor.ts +119 -0
- package/src/ui/overrideSettingsList.ts +682 -0
- package/src/ui/serverListEditor.ts +32 -0
- package/src/ui/serverSettingsList.ts +466 -0
- package/src/ui/strings.ts +127 -0
- package/src/utils/errors.ts +5 -0
- package/src/utils/settingsStore.ts +56 -0
- package/src/utils/urls.ts +16 -0
- package/tests/commandManager.test.ts +346 -11
- package/tests/dialog.test.ts +186 -0
- package/tests/events.test.ts +120 -88
- package/tests/legacyModel.test.ts +4 -19
- package/tests/mocks.ts +149 -32
- package/tests/overrides.test.ts +352 -0
- package/tests/server.test.ts +42 -40
- package/tests/serverManager.test.ts +264 -55
- package/tests/settings.test.ts +654 -51
- package/tests/settingsStore.test.ts +190 -0
- package/tests/singleModel.test.ts +32 -0
- package/tests/sseManager.test.ts +88 -11
- package/src/interfaces/auth.ts +0 -6
- package/src/utils/cache.ts +0 -39
- package/src/utils/mutex.ts +0 -24
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { ModelCost, ModelCostRates } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { LlamaServer, ModelOverride } from "../interfaces/settings";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Parses a raw cost-field value. Empty input means zero (treated as unset
|
|
6
|
+
* — the key is removed from the settings). Everything else must be a
|
|
7
|
+
* finite, non-negative number.
|
|
8
|
+
*
|
|
9
|
+
* @returns The parsed value, or `null` when the input is invalid
|
|
10
|
+
*/
|
|
11
|
+
export const parseCostValue = (raw: string): number | null => {
|
|
12
|
+
const v = raw.trim();
|
|
13
|
+
if (v.length === 0) return 0;
|
|
14
|
+
const n = Number(v);
|
|
15
|
+
if (isNaN(n) || !isFinite(n) || n < 0) return null;
|
|
16
|
+
return n;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Returns a copy of `cost` with `field` set to `value`. A `0` (or
|
|
21
|
+
* non-finite) value removes the field — unset cost fields default to
|
|
22
|
+
* zero at read time — and when no fields remain, returns `undefined` so
|
|
23
|
+
* the whole `cost` object can be dropped. Immutable.
|
|
24
|
+
*/
|
|
25
|
+
export const applyCostFieldValue = (
|
|
26
|
+
cost: ModelOverride["cost"],
|
|
27
|
+
field: keyof ModelCostRates,
|
|
28
|
+
value: number,
|
|
29
|
+
): Partial<ModelCost> | undefined => {
|
|
30
|
+
const next = { ...cost };
|
|
31
|
+
if (isFinite(value) && value > 0) next[field] = value;
|
|
32
|
+
else delete next[field];
|
|
33
|
+
return Object.keys(next).length > 0 ? next : undefined;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns a new list with the server at `serverIndex` updated so its
|
|
38
|
+
* `overrides` map gains a new `pattern → override` entry. Immutable.
|
|
39
|
+
*/
|
|
40
|
+
export const addOverrideEntry = (
|
|
41
|
+
servers: LlamaServer[],
|
|
42
|
+
serverIndex: number,
|
|
43
|
+
pattern: string,
|
|
44
|
+
override: ModelOverride = {},
|
|
45
|
+
): LlamaServer[] =>
|
|
46
|
+
servers.map((server, i) => {
|
|
47
|
+
if (i !== serverIndex) return server;
|
|
48
|
+
const overrides = { ...server.overrides, [pattern]: override };
|
|
49
|
+
return { ...server, overrides };
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Returns a new list with the override entry at `entryIndex` (within the
|
|
54
|
+
* server's overrides map) replaced by `pattern → override` in a single
|
|
55
|
+
* mutation — used both for renaming the pattern and for editing its
|
|
56
|
+
* fields. The entry keeps its position in the map's iteration order.
|
|
57
|
+
* Immutable.
|
|
58
|
+
*/
|
|
59
|
+
export const updateOverrideEntry = (
|
|
60
|
+
servers: LlamaServer[],
|
|
61
|
+
serverIndex: number,
|
|
62
|
+
entryIndex: number,
|
|
63
|
+
pattern: string,
|
|
64
|
+
override: ModelOverride,
|
|
65
|
+
): LlamaServer[] =>
|
|
66
|
+
servers.map((server, i) => {
|
|
67
|
+
if (i !== serverIndex) return server;
|
|
68
|
+
const overrides = server.overrides ?? {};
|
|
69
|
+
const entries = Object.entries(overrides).map(([k, v], j) =>
|
|
70
|
+
j === entryIndex ? [pattern, override] : [k, v],
|
|
71
|
+
);
|
|
72
|
+
return { ...server, overrides: Object.fromEntries(entries) };
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Returns a new list with the override entry at `entryIndex` (within the
|
|
77
|
+
* server's overrides map) removed. Immutable.
|
|
78
|
+
*/
|
|
79
|
+
export const removeOverrideEntry = (
|
|
80
|
+
servers: LlamaServer[],
|
|
81
|
+
serverIndex: number,
|
|
82
|
+
entryIndex: number,
|
|
83
|
+
): LlamaServer[] =>
|
|
84
|
+
servers.map((server, i) => {
|
|
85
|
+
if (i !== serverIndex) return server;
|
|
86
|
+
const overrides = server.overrides ?? {};
|
|
87
|
+
const entries = Object.entries(overrides).filter(
|
|
88
|
+
(_, j) => j !== entryIndex,
|
|
89
|
+
);
|
|
90
|
+
return { ...server, overrides: Object.fromEntries(entries) };
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Formats an override as a summary shown in the entry rows:
|
|
95
|
+
* `input: $0.2, output: $0.6, cache read: $0.01, capabilities: text,image,
|
|
96
|
+
* reasoning: false` — cost fields that are zero or undefined are omitted
|
|
97
|
+
* for brevity; `—` when everything is empty.
|
|
98
|
+
*/
|
|
99
|
+
export const formatOverrideSummary = (override: ModelOverride): string => {
|
|
100
|
+
const parts: string[] = [];
|
|
101
|
+
const cost = override.cost ?? {};
|
|
102
|
+
if (cost.input) parts.push(`input: $${cost.input}`);
|
|
103
|
+
if (cost.output) parts.push(`output: $${cost.output}`);
|
|
104
|
+
if (cost.cacheRead) parts.push(`cache read: $${cost.cacheRead}`);
|
|
105
|
+
if (cost.cacheWrite) parts.push(`cache write: $${cost.cacheWrite}`);
|
|
106
|
+
if (override.capabilities?.length) {
|
|
107
|
+
parts.push(`capabilities: ${override.capabilities.join(",")}`);
|
|
108
|
+
}
|
|
109
|
+
if (override.reasoning !== undefined) {
|
|
110
|
+
parts.push(`reasoning: ${override.reasoning}`);
|
|
111
|
+
}
|
|
112
|
+
if (override.contextSize !== undefined) {
|
|
113
|
+
parts.push(`contextSize: ${override.contextSize}`);
|
|
114
|
+
}
|
|
115
|
+
if (override.maxTokens !== undefined) {
|
|
116
|
+
parts.push(`maxTokens: ${override.maxTokens}`);
|
|
117
|
+
}
|
|
118
|
+
return parts.length > 0 ? parts.join(", ") : "—";
|
|
119
|
+
};
|