@tomradex/domain 0.2.19 → 0.2.24
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/dist/derive.d.ts +1 -2
- package/dist/derive.js +2 -2
- package/dist/errors.d.ts +0 -7
- package/dist/errors.js +0 -43
- package/dist/model-errors.d.ts +9 -0
- package/dist/model-errors.js +44 -0
- package/dist/query.d.ts +0 -4
- package/dist/query.js +3 -3
- package/dist/words.d.ts +0 -1
- package/dist/words.js +1 -1
- package/package.json +1 -1
package/dist/derive.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Author, Item, Provenance } from "./types.js";
|
|
2
2
|
export declare const isAi: (by: Author | string) => boolean;
|
|
3
|
-
export declare const isSync: (by: Author | string) => boolean;
|
|
4
3
|
/** Derived, never stored: a locked item reads as locked whoever wrote it last. */
|
|
5
4
|
export declare function provenanceOf(item: Pick<Item, "humanLocked" | "updatedBy">): Provenance;
|
|
6
|
-
/** 'Tomrade
|
|
5
|
+
/** 'Tomrade Desktop' -> 'TOM'. Falls back to a generic prefix for nameless input. */
|
|
7
6
|
export declare function keyPrefixFor(name: string): string;
|
|
8
7
|
//# sourceMappingURL=derive.d.ts.map
|
package/dist/derive.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export const isAi = (by) => by.startsWith("ai:");
|
|
2
|
-
|
|
2
|
+
const isSync = (by) => by.startsWith("sync:");
|
|
3
3
|
/** Derived, never stored: a locked item reads as locked whoever wrote it last. */
|
|
4
4
|
export function provenanceOf(item) {
|
|
5
5
|
if (item.humanLocked)
|
|
6
6
|
return "locked";
|
|
7
7
|
return isAi(item.updatedBy) ? "ai" : isSync(item.updatedBy) ? "sync" : "human";
|
|
8
8
|
}
|
|
9
|
-
/** 'Tomrade
|
|
9
|
+
/** 'Tomrade Desktop' -> 'TOM'. Falls back to a generic prefix for nameless input. */
|
|
10
10
|
export function keyPrefixFor(name) {
|
|
11
11
|
const letters = name.toUpperCase().replace(/[^A-Z]/g, "");
|
|
12
12
|
return letters.slice(0, 3) || "ISS";
|
package/dist/errors.d.ts
CHANGED
|
@@ -55,13 +55,6 @@ export declare class FieldDefinitionError extends Error {
|
|
|
55
55
|
* `slow`: the model was reached but gave no answer in time; only a check that waits for one says it.
|
|
56
56
|
*/
|
|
57
57
|
export type ModelErrorKind = "auth" | "quota" | "rate" | "model" | "server" | "network" | "slow" | "other";
|
|
58
|
-
/** Why a model turned a working key down: the wrong API for it, not open to this key's tier or account, or not known. */
|
|
59
|
-
export type ModelRefusal = "method" | "tier" | "unknown";
|
|
60
|
-
export declare function modelRefusal(message: string): ModelRefusal | null;
|
|
61
|
-
/** Only a key the provider calls wrong or missing is `auth`; a model it will not serve this key is `model`, even on a 403. */
|
|
62
|
-
export declare function modelErrorKind(message: string): ModelErrorKind;
|
|
63
|
-
/** The provider's own words in a failed call's detail (its JSON `message`), or null; cut short where the detail was. */
|
|
64
|
-
export declare function providerMessage(detail: string): string | null;
|
|
65
58
|
/**
|
|
66
59
|
* An undo aimed at one write — a toast's — refused because the thing changed
|
|
67
60
|
* again since. The marker survives IPC's message wrapping, so the renderer can
|
package/dist/errors.js
CHANGED
|
@@ -96,49 +96,6 @@ export class FieldDefinitionError extends Error {
|
|
|
96
96
|
this.name = "FieldDefinitionError";
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
const BAD_KEY = /\b401\b|authenticat|unauthori[sz]ed|invalid[ _-]?(api[ _-]?)?key|incorrect api key|api[ _-]?key[ _-]?(not valid|invalid|expired|missing|required)|(missing|no) api[ _-]?key/i;
|
|
100
|
-
export function modelRefusal(message) {
|
|
101
|
-
if (/not supported for (generateContent|this (api|method|endpoint))|not a chat model|only supported (in|on|by) (the )?(v1\/)?responses|not supported (in|on|by) (the )?(v1\/)?chat\/completions|does not support (chat|generateContent)/i.test(message))
|
|
102
|
-
return "method";
|
|
103
|
-
if (/model.{0,40}(not found|does not exist|not exist|unknown)|no such model|unknown model|model_not_found/i.test(message) && !/not have access to model/i.test(message))
|
|
104
|
-
return "unknown";
|
|
105
|
-
if (/free[ _-]?tier\w*.{0,80}\blimit: ?0\b|not available (on|for|in) (the |your |this )?(free |current )?(tier|plan)|not have access to (the |this )?model|not have permission to (use|access) (the |this )?model|not allow-?listed|model.{0,60}(not available|unavailable) (to|for) (you|this)/i.test(message))
|
|
106
|
-
return "tier";
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
/** Only a key the provider calls wrong or missing is `auth`; a model it will not serve this key is `model`, even on a 403. */
|
|
110
|
-
export function modelErrorKind(message) {
|
|
111
|
-
if (BAD_KEY.test(message))
|
|
112
|
-
return "auth";
|
|
113
|
-
if (modelRefusal(message))
|
|
114
|
-
return "model";
|
|
115
|
-
if (/\b403\b|api key|permission denied|forbidden/i.test(message))
|
|
116
|
-
return "auth";
|
|
117
|
-
if (/\b402\b|insufficient|balance|quota|billing|credit/i.test(message))
|
|
118
|
-
return "quota";
|
|
119
|
-
if (/\b429\b|rate.?limit|too many requests/i.test(message))
|
|
120
|
-
return "rate";
|
|
121
|
-
if (/\b404\b|model.{0,40}(not found|does not exist|not exist|unknown|invalid)|no such model|unknown model/i.test(message))
|
|
122
|
-
return "model";
|
|
123
|
-
if (/\b5\d\d\b|overloaded|bad gateway|service unavailable/i.test(message))
|
|
124
|
-
return "server";
|
|
125
|
-
// "Connection error." is how the OpenAI and Anthropic SDKs — the built-in pi's — say the service was not reached.
|
|
126
|
-
if (/fetch failed|ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|ETIMEDOUT|network|connection error|timed? ?out|socket hang up|certificate/i.test(message))
|
|
127
|
-
return "network";
|
|
128
|
-
return "other";
|
|
129
|
-
}
|
|
130
|
-
/** The provider's own words in a failed call's detail (its JSON `message`), or null; cut short where the detail was. */
|
|
131
|
-
export function providerMessage(detail) {
|
|
132
|
-
const found = /"message"\s*:\s*"((?:[^"\\]|\\.)*)("|$)/.exec(detail);
|
|
133
|
-
if (!found?.[1].trim())
|
|
134
|
-
return null;
|
|
135
|
-
let said = found[1];
|
|
136
|
-
try {
|
|
137
|
-
said = JSON.parse(`"${said.replace(/\\$/, "")}"`);
|
|
138
|
-
}
|
|
139
|
-
catch { }
|
|
140
|
-
return found[2] ? said : `${said}…`;
|
|
141
|
-
}
|
|
142
99
|
/**
|
|
143
100
|
* An undo aimed at one write — a toast's — refused because the thing changed
|
|
144
101
|
* again since. The marker survives IPC's message wrapping, so the renderer can
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ModelErrorKind } from "./errors.js";
|
|
2
|
+
/** Why a model turned a working key down: the wrong API for it, not open to this key's tier or account, or not known. */
|
|
3
|
+
export type ModelRefusal = "method" | "tier" | "unknown";
|
|
4
|
+
export declare function modelRefusal(message: string): ModelRefusal | null;
|
|
5
|
+
/** Only a key the provider calls wrong or missing is `auth`; a model it will not serve this key is `model`, even on a 403. */
|
|
6
|
+
export declare function modelErrorKind(message: string): ModelErrorKind;
|
|
7
|
+
/** The provider's own words in a failed call's detail (its JSON `message`), or null; cut short where the detail was. */
|
|
8
|
+
export declare function providerMessage(detail: string): string | null;
|
|
9
|
+
//# sourceMappingURL=model-errors.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const BAD_KEY = /\b401\b|authenticat|unauthori[sz]ed|invalid[ _-]?(api[ _-]?)?key|incorrect api key|api[ _-]?key[ _-]?(not valid|invalid|expired|missing|required)|(missing|no) api[ _-]?key/i;
|
|
2
|
+
export function modelRefusal(message) {
|
|
3
|
+
if (/not supported for (generateContent|this (api|method|endpoint))|not a chat model|only supported (in|on|by) (the )?(v1\/)?responses|not supported (in|on|by) (the )?(v1\/)?chat\/completions|does not support (chat|generateContent)/i.test(message))
|
|
4
|
+
return "method";
|
|
5
|
+
if (/model.{0,40}(not found|does not exist|not exist|unknown)|no such model|unknown model|model_not_found/i.test(message) && !/not have access to model/i.test(message))
|
|
6
|
+
return "unknown";
|
|
7
|
+
if (/free[ _-]?tier\w*.{0,80}\blimit: ?0\b|not available (on|for|in) (the |your |this )?(free |current )?(tier|plan)|not have access to (the |this )?model|not have permission to (use|access) (the |this )?model|not allow-?listed|model.{0,60}(not available|unavailable) (to|for) (you|this)/i.test(message))
|
|
8
|
+
return "tier";
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
/** Only a key the provider calls wrong or missing is `auth`; a model it will not serve this key is `model`, even on a 403. */
|
|
12
|
+
export function modelErrorKind(message) {
|
|
13
|
+
if (BAD_KEY.test(message))
|
|
14
|
+
return "auth";
|
|
15
|
+
if (modelRefusal(message))
|
|
16
|
+
return "model";
|
|
17
|
+
if (/\b403\b|api key|permission denied|forbidden/i.test(message))
|
|
18
|
+
return "auth";
|
|
19
|
+
if (/\b402\b|insufficient|balance|quota|billing|credit/i.test(message))
|
|
20
|
+
return "quota";
|
|
21
|
+
if (/\b429\b|rate.?limit|too many requests/i.test(message))
|
|
22
|
+
return "rate";
|
|
23
|
+
if (/\b404\b|model.{0,40}(not found|does not exist|not exist|unknown|invalid)|no such model|unknown model/i.test(message))
|
|
24
|
+
return "model";
|
|
25
|
+
if (/\b5\d\d\b|overloaded|bad gateway|service unavailable/i.test(message))
|
|
26
|
+
return "server";
|
|
27
|
+
// "Connection error." is how the OpenAI and Anthropic SDKs — the built-in pi's — say the service was not reached.
|
|
28
|
+
if (/fetch failed|ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|ETIMEDOUT|network|connection error|timed? ?out|socket hang up|certificate/i.test(message))
|
|
29
|
+
return "network";
|
|
30
|
+
return "other";
|
|
31
|
+
}
|
|
32
|
+
/** The provider's own words in a failed call's detail (its JSON `message`), or null; cut short where the detail was. */
|
|
33
|
+
export function providerMessage(detail) {
|
|
34
|
+
const found = /"message"\s*:\s*"((?:[^"\\]|\\.)*)("|$)/.exec(detail);
|
|
35
|
+
if (!found?.[1].trim())
|
|
36
|
+
return null;
|
|
37
|
+
let said = found[1];
|
|
38
|
+
try {
|
|
39
|
+
said = JSON.parse(`"${said.replace(/\\$/, "")}"`);
|
|
40
|
+
}
|
|
41
|
+
catch { }
|
|
42
|
+
return found[2] ? said : `${said}…`;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=model-errors.js.map
|
package/dist/query.d.ts
CHANGED
|
@@ -40,7 +40,6 @@ export interface ViewQuery {
|
|
|
40
40
|
/** Graph layout: the contributed graph whose edges are drawn. */
|
|
41
41
|
graph: string | null;
|
|
42
42
|
}
|
|
43
|
-
export declare const EMPTY_QUERY: ViewQuery;
|
|
44
43
|
/** Fill a partially stored query so every consumer sees the full shape. */
|
|
45
44
|
export declare const normalizeQuery: (q: Partial<ViewQuery> | null | undefined) => ViewQuery;
|
|
46
45
|
export interface QueryContext {
|
|
@@ -52,7 +51,6 @@ export interface QueryContext {
|
|
|
52
51
|
}
|
|
53
52
|
/** A `YYYY-MM-DD` bound against an epoch-ms value covers the whole day it names. */
|
|
54
53
|
export declare function dayBound(value: FieldValue | null | undefined, op: "gte" | "lte"): number | null;
|
|
55
|
-
export declare function matchesClause(item: Item, clause: FilterClause): boolean;
|
|
56
54
|
export declare const matchesFilter: (item: Item, filter: FilterClause[]) => boolean;
|
|
57
55
|
/**
|
|
58
56
|
* The terms of a search: whitespace-separated words, except that a run in
|
|
@@ -62,8 +60,6 @@ export declare const matchesFilter: (item: Item, filter: FilterClause[]) => bool
|
|
|
62
60
|
export declare function searchTerms(search: string): string[];
|
|
63
61
|
/** Every term appears, case aside, in the ticket's key, title or body — what the items index matches, plus the key. */
|
|
64
62
|
export declare function matchesSearch(item: Item, terms: string[]): boolean;
|
|
65
|
-
/** A comparable for one sort key: numbers for numeric fields, strings otherwise, null when empty. */
|
|
66
|
-
export declare function sortKeyOf(item: Item, fieldId: string, ctx: QueryContext): number | string | null;
|
|
67
63
|
/** Empty values sort last whichever direction; ties fall through to manual rank, then recency. */
|
|
68
64
|
export declare function compareItems(a: Item, b: Item, sortBy: SortKey[], ctx: QueryContext, rankOf: (item: Item) => number): number;
|
|
69
65
|
/** The keys a groupable field can take, in the field's order, with the empty key last where it applies. */
|
package/dist/query.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CHECKED, EMPTY_KEY, fieldValueOf } from "./fields.js";
|
|
2
2
|
export const LAYOUTS = ["board", "table", "graph"];
|
|
3
|
-
|
|
3
|
+
const EMPTY_QUERY = { filter: [], columnBy: "status", columns: [], groupBy: null, sortBy: [], fields: [], wip: {}, graph: null };
|
|
4
4
|
/** Fill a partially stored query so every consumer sees the full shape. */
|
|
5
5
|
export const normalizeQuery = (q) => ({ ...EMPTY_QUERY, ...(q ?? {}), wip: { ...(q?.wip ?? {}) } });
|
|
6
6
|
const norm = (v) => (v === null ? null : String(v));
|
|
@@ -16,7 +16,7 @@ export function dayBound(value, op) {
|
|
|
16
16
|
return null;
|
|
17
17
|
return op === "lte" ? t + DAY - 1 : t;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
function matchesClause(item, clause) {
|
|
20
20
|
const raw = fieldValueOf(item, clause.field);
|
|
21
21
|
const values = Array.isArray(raw) ? raw : raw === null ? [] : [raw];
|
|
22
22
|
switch (clause.op) {
|
|
@@ -93,7 +93,7 @@ export function matchesSearch(item, terms) {
|
|
|
93
93
|
return terms.every((term) => text.includes(term.toLowerCase()));
|
|
94
94
|
}
|
|
95
95
|
/** A comparable for one sort key: numbers for numeric fields, strings otherwise, null when empty. */
|
|
96
|
-
|
|
96
|
+
function sortKeyOf(item, fieldId, ctx) {
|
|
97
97
|
const raw = fieldValueOf(item, fieldId);
|
|
98
98
|
if (raw === null || Array.isArray(raw))
|
|
99
99
|
return null;
|
package/dist/words.d.ts
CHANGED
|
@@ -22,7 +22,6 @@ export interface Speak<E extends Record<string, string>> {
|
|
|
22
22
|
readonly locale: LanguageTag;
|
|
23
23
|
}
|
|
24
24
|
export type WordBook<E extends Record<string, string>> = (locale: unknown) => Speak<E>;
|
|
25
|
-
export declare const fillSlots: (template: string, vars?: Record<string, string | number>) => string;
|
|
26
25
|
export declare function defineWords<const E extends Record<string, string>, const Z extends Record<string, string>>(id: string, book: {
|
|
27
26
|
en: E;
|
|
28
27
|
zh: Z & Translation<E, Z>;
|
package/dist/words.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { languageTag, sameSlots } from "./language.js";
|
|
2
2
|
export const wordsLocale = (locale) => (locale === "zh" ? "zh" : "en");
|
|
3
|
-
|
|
3
|
+
const fillSlots = (template, vars) => vars ? template.replace(/\{\{(\w+)\}\}/g, (_, name) => String(vars[name] ?? "")) : template;
|
|
4
4
|
/** Every book's English, by id: what a language pack translates. */
|
|
5
5
|
const english = new Map();
|
|
6
6
|
/** Language → book → key: what installed language packs bring, each layer kept apart so one can be taken back. */
|