@chatpanel/events 0.33.1 → 0.47.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/backup-envelope.js +221 -0
- package/curate.js +509 -0
- package/distance.js +124 -0
- package/entitlement.js +298 -0
- package/entity.js +354 -0
- package/flowchart.js +350 -97
- package/index.js +78 -0
- package/knowledge-derive.js +267 -0
- package/knowledge.js +221 -0
- package/library.js +265 -0
- package/omni.js +125 -0
- package/package.json +43 -11
- package/promotion.js +171 -0
- package/redaction-tokens.js +61 -0
- package/ref.js +4 -1
- package/subject-kinds.js +5 -0
- package/subject-name.js +96 -0
- package/sync-plan.js +170 -0
- package/synthesis.js +123 -0
- package/theme.js +155 -0
- package/voice-intents.js +5 -23
package/theme.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// THE PALETTE, AS DATA — so every client paints the same product.
|
|
2
|
+
//
|
|
3
|
+
// These values are not new. They are the extension's shipped dashboard stylesheet
|
|
4
|
+
// (`meetings.css`, which `notes.css` and `briefs.css` both build on), lifted out of CSS and
|
|
5
|
+
// into a form a non-CSS client can read. A SwiftUI or Compose client cannot import a
|
|
6
|
+
// stylesheet, and a desktop app that re-types the hexes will drift the first time one is
|
|
7
|
+
// tuned — which is the same failure mode as the record model, in a smaller coat.
|
|
8
|
+
//
|
|
9
|
+
// WHAT BELONGS HERE AND WHAT DOES NOT. Tokens are shared; layout is not. A color named
|
|
10
|
+
// `--risk` means the same thing in every surface, so it is a contract. The width of a rail,
|
|
11
|
+
// the height of a row and the shape of a shadow are rendering decisions each platform makes
|
|
12
|
+
// for itself, and pretending otherwise is how a Mac app ends up looking like a web page.
|
|
13
|
+
//
|
|
14
|
+
// TWO THEMES, ONE SET OF NAMES. Every token exists in both themes — a name defined in only
|
|
15
|
+
// one is what produces the invisible-text-in-light-mode bug. `TOKEN_NAMES` is the guard:
|
|
16
|
+
// a test asserts both themes carry exactly it.
|
|
17
|
+
|
|
18
|
+
export const THEMES = Object.freeze(['light', 'dark']);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Semantic roles, and what each is FOR — the part a hex value cannot carry.
|
|
22
|
+
*
|
|
23
|
+
* `bg` is the window; `card` is a raised surface on it; `elev` is raised again (a popover);
|
|
24
|
+
* `field` is a recessed surface (an input, a well). Getting that ladder wrong is why some
|
|
25
|
+
* dark UIs look flat: the surfaces must step in one direction.
|
|
26
|
+
*/
|
|
27
|
+
export const TOKEN_ROLES = Object.freeze({
|
|
28
|
+
bg: 'the window ground',
|
|
29
|
+
card: 'a surface raised off the ground',
|
|
30
|
+
elev: 'a surface raised off a card — popovers, overlays',
|
|
31
|
+
field: 'a recessed surface — inputs, wells, meters',
|
|
32
|
+
border: 'hairline separators',
|
|
33
|
+
borderStrong: 'a border that must be seen, not merely felt',
|
|
34
|
+
text: 'primary reading colour',
|
|
35
|
+
muted: 'secondary text that is still content',
|
|
36
|
+
faint: 'labels, captions and metadata',
|
|
37
|
+
accent: 'the product colour — selection, links, the active mode',
|
|
38
|
+
accentWeak: 'accent as a background wash',
|
|
39
|
+
decision: 'something settled',
|
|
40
|
+
risk: 'something that can hurt',
|
|
41
|
+
question: 'something open',
|
|
42
|
+
person: 'a person subject',
|
|
43
|
+
topic: 'a topic subject',
|
|
44
|
+
tag: 'a tag subject',
|
|
45
|
+
title: 'a title subject',
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const TOKEN_NAMES = Object.freeze(Object.keys(TOKEN_ROLES));
|
|
49
|
+
|
|
50
|
+
export const LIGHT = Object.freeze({
|
|
51
|
+
bg: '#f5f6f8',
|
|
52
|
+
card: '#ffffff',
|
|
53
|
+
elev: '#ffffff',
|
|
54
|
+
field: '#f7f8fa',
|
|
55
|
+
border: '#e4e7ec',
|
|
56
|
+
borderStrong: '#d3d8e0',
|
|
57
|
+
text: '#181b20',
|
|
58
|
+
muted: '#646b76',
|
|
59
|
+
faint: '#8a909b',
|
|
60
|
+
accent: '#5b5bf0',
|
|
61
|
+
accentWeak: 'rgba(91,91,240,.10)',
|
|
62
|
+
decision: '#15a34a',
|
|
63
|
+
risk: '#dc2626',
|
|
64
|
+
question: '#b45309',
|
|
65
|
+
person: '#7c4dff',
|
|
66
|
+
topic: '#0b84ff',
|
|
67
|
+
tag: '#17a673',
|
|
68
|
+
title: '#b7791f',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export const DARK = Object.freeze({
|
|
72
|
+
bg: '#0e1014',
|
|
73
|
+
card: '#16191f',
|
|
74
|
+
elev: '#1b1f26',
|
|
75
|
+
field: '#1f242c',
|
|
76
|
+
border: '#272c34',
|
|
77
|
+
borderStrong: '#353c46',
|
|
78
|
+
text: '#e9ebee',
|
|
79
|
+
muted: '#9aa1ac',
|
|
80
|
+
faint: '#6b7280',
|
|
81
|
+
accent: '#818cf8',
|
|
82
|
+
accentWeak: 'rgba(129,140,248,.13)',
|
|
83
|
+
decision: '#34d399',
|
|
84
|
+
risk: '#f87171',
|
|
85
|
+
question: '#fbbf24',
|
|
86
|
+
person: '#7c4dff',
|
|
87
|
+
topic: '#0b84ff',
|
|
88
|
+
tag: '#17a673',
|
|
89
|
+
title: '#b7791f',
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export const PALETTES = Object.freeze({ light: LIGHT, dark: DARK });
|
|
93
|
+
|
|
94
|
+
/** Shape values that are the same in both themes, so they are stated once. */
|
|
95
|
+
export const SHAPE = Object.freeze({
|
|
96
|
+
radius: '13px',
|
|
97
|
+
radiusSm: '9px',
|
|
98
|
+
radiusXs: '5px',
|
|
99
|
+
mono: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
100
|
+
sans: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export function paletteFor(theme) {
|
|
104
|
+
return PALETTES[theme] || DARK;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** camelCase → the `--kebab-case` custom property the stylesheets already use. */
|
|
108
|
+
export function cssVarName(token) {
|
|
109
|
+
return `--${String(token).replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`)}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A palette as CSS custom-property declarations.
|
|
114
|
+
*
|
|
115
|
+
* Returns only the declarations — the caller wraps them in whatever selector its theming
|
|
116
|
+
* strategy needs (`:root`, `[data-theme="dark"]`, a media query). Deciding the selector here
|
|
117
|
+
* would force one strategy on every client.
|
|
118
|
+
*/
|
|
119
|
+
export function toCssVars(theme, { includeShape = false } = {}) {
|
|
120
|
+
const palette = paletteFor(theme);
|
|
121
|
+
const lines = TOKEN_NAMES.map((name) => ` ${cssVarName(name)}: ${palette[name]};`);
|
|
122
|
+
if (includeShape) {
|
|
123
|
+
for (const [k, v] of Object.entries(SHAPE)) lines.push(` ${cssVarName(k)}: ${v};`);
|
|
124
|
+
}
|
|
125
|
+
return lines.join('\n');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* A complete, theme-aware stylesheet block for a web client.
|
|
130
|
+
*
|
|
131
|
+
* Three selectors, and all three are needed: bare `:root` is the light default, the media
|
|
132
|
+
* query serves the "system" setting that stamps no attribute, and `[data-theme]` lets an
|
|
133
|
+
* explicit choice win in BOTH directions. A client that ships only the media query cannot
|
|
134
|
+
* offer a theme switch that overrides the OS.
|
|
135
|
+
*/
|
|
136
|
+
export function themeStylesheet() {
|
|
137
|
+
return [
|
|
138
|
+
`:root {\n${toCssVars('light', { includeShape: true })}\n color-scheme: light;\n}`,
|
|
139
|
+
`@media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n${toCssVars('dark')}\n color-scheme: dark;\n }\n}`,
|
|
140
|
+
`:root[data-theme="dark"] {\n${toCssVars('dark')}\n color-scheme: dark;\n}`,
|
|
141
|
+
`:root[data-theme="light"] {\n${toCssVars('light')}\n color-scheme: light;\n}`,
|
|
142
|
+
].join('\n\n');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Resolve the theme actually in force.
|
|
147
|
+
*
|
|
148
|
+
* `preference` is what the user chose — `'light'`, `'dark'` or `'system'`; `systemDark` is
|
|
149
|
+
* what the OS reports. Kept as a function because three surfaces need the same answer and
|
|
150
|
+
* two of them cannot read a media query.
|
|
151
|
+
*/
|
|
152
|
+
export function resolveTheme(preference, systemDark = false) {
|
|
153
|
+
if (preference === 'light' || preference === 'dark') return preference;
|
|
154
|
+
return systemDark ? 'dark' : 'light';
|
|
155
|
+
}
|
package/voice-intents.js
CHANGED
|
@@ -34,6 +34,11 @@ import {
|
|
|
34
34
|
// answer in this package — a second copy here would drift, and two features would disagree
|
|
35
35
|
// about the same caption on the same screen.
|
|
36
36
|
import { DANGLING_TAILS } from './schedule.js';
|
|
37
|
+
// The wake matcher's fuzzy compare. It lived here until the maintenance pass needed the
|
|
38
|
+
// same question answered; re-exported so every existing caller (and index.js) is unchanged.
|
|
39
|
+
import { editDistance } from './distance.js';
|
|
40
|
+
|
|
41
|
+
export { editDistance };
|
|
37
42
|
|
|
38
43
|
export class VoiceIntentError extends Error {
|
|
39
44
|
constructor(code, message) { super(message); this.name = 'VoiceIntentError'; this.code = code; }
|
|
@@ -56,29 +61,6 @@ const MAX_WAKE_TOKENS = 3;
|
|
|
56
61
|
// and a wake phrase longer than this is a sentence, not a wake phrase.
|
|
57
62
|
const WAKE_TOKEN_CEILING = 8;
|
|
58
63
|
|
|
59
|
-
// Bounded Levenshtein — returns early once the distance cannot come in under `max`, so a
|
|
60
|
-
// wake scan over a long transcript stays linear in practice.
|
|
61
|
-
export function editDistance(a, b, max = Infinity) {
|
|
62
|
-
if (a === b) return 0;
|
|
63
|
-
if (Math.abs(a.length - b.length) > max) return max + 1;
|
|
64
|
-
let prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
65
|
-
for (let i = 1; i <= a.length; i++) {
|
|
66
|
-
const cur = [i];
|
|
67
|
-
let best = i;
|
|
68
|
-
for (let j = 1; j <= b.length; j++) {
|
|
69
|
-
cur[j] = Math.min(
|
|
70
|
-
prev[j] + 1,
|
|
71
|
-
cur[j - 1] + 1,
|
|
72
|
-
prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1),
|
|
73
|
-
);
|
|
74
|
-
if (cur[j] < best) best = cur[j];
|
|
75
|
-
}
|
|
76
|
-
if (best > max) return max + 1;
|
|
77
|
-
prev = cur;
|
|
78
|
-
}
|
|
79
|
-
return prev[b.length];
|
|
80
|
-
}
|
|
81
|
-
|
|
82
64
|
// Lowercase and blank out punctuation WITHOUT changing length, so every offset computed
|
|
83
65
|
// against the normalised copy still points at the same character of the original. The
|
|
84
66
|
// command text handed back to the user keeps its capitals and its apostrophes; matching
|