@2lab.ai/ui 0.0.0-stage → 0.2.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.
Files changed (60) hide show
  1. package/README.md +55 -2
  2. package/dist/agent-inbox.js +1061 -0
  3. package/dist/agent-inbox.js.map +1 -0
  4. package/dist/agent-queue.js +1610 -0
  5. package/dist/agent-queue.js.map +1 -0
  6. package/dist/agent-run.js +859 -0
  7. package/dist/agent-run.js.map +1 -0
  8. package/dist/ai-answer.js +687 -0
  9. package/dist/ai-answer.js.map +1 -0
  10. package/dist/components/agent-inbox/agent-inbox.d.ts +158 -0
  11. package/dist/components/agent-inbox/index.d.ts +2 -0
  12. package/dist/components/agent-inbox/styles.d.ts +6 -0
  13. package/dist/components/agent-queue/agent-queue.d.ts +41 -0
  14. package/dist/components/agent-queue/index.d.ts +6 -0
  15. package/dist/components/agent-queue/logic.d.ts +261 -0
  16. package/dist/components/agent-queue/strings.d.ts +473 -0
  17. package/dist/components/agent-queue/styles.d.ts +8 -0
  18. package/dist/components/agent-run/agent-run.d.ts +273 -0
  19. package/dist/components/agent-run/index.d.ts +2 -0
  20. package/dist/components/agent-run/styles.d.ts +6 -0
  21. package/dist/components/ai-answer/ai-answer.d.ts +92 -0
  22. package/dist/components/ai-answer/index.d.ts +2 -0
  23. package/dist/components/ai-answer/styles.d.ts +2 -0
  24. package/dist/components/context-window/context-window.d.ts +156 -0
  25. package/dist/components/context-window/index.d.ts +2 -0
  26. package/dist/components/context-window/styles.d.ts +2 -0
  27. package/dist/components/memory-panel/index.d.ts +2 -0
  28. package/dist/components/memory-panel/memory-panel.d.ts +101 -0
  29. package/dist/components/memory-panel/styles.d.ts +2 -0
  30. package/dist/components/model-picker/index.d.ts +2 -0
  31. package/dist/components/model-picker/model-picker.d.ts +136 -0
  32. package/dist/components/model-picker/morph.d.ts +9 -0
  33. package/dist/components/model-picker/styles.d.ts +6 -0
  34. package/dist/components/tool-call-card/index.d.ts +7 -0
  35. package/dist/components/tool-call-card/logic.d.ts +87 -0
  36. package/dist/components/tool-call-card/strings.d.ts +94 -0
  37. package/dist/components/tool-call-card/styles.d.ts +5 -0
  38. package/dist/components/tool-call-card/tool-call-card.d.ts +49 -0
  39. package/dist/components/tool-call-card/tool-call-group.d.ts +32 -0
  40. package/dist/context-window.js +384 -0
  41. package/dist/context-window.js.map +1 -0
  42. package/dist/core/element.d.ts +41 -0
  43. package/dist/core/format.d.ts +14 -0
  44. package/dist/core/html.d.ts +10 -0
  45. package/dist/core/tokens.d.ts +14 -0
  46. package/dist/format-BBGWXPzk.js +51 -0
  47. package/dist/format-BBGWXPzk.js.map +1 -0
  48. package/dist/html-elD6Bb_u.js +175 -0
  49. package/dist/html-elD6Bb_u.js.map +1 -0
  50. package/dist/index.d.ts +16 -0
  51. package/dist/index.js +129 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/memory-panel.js +1255 -0
  54. package/dist/memory-panel.js.map +1 -0
  55. package/dist/model-picker.js +858 -0
  56. package/dist/model-picker.js.map +1 -0
  57. package/dist/tokens.css +4 -0
  58. package/dist/tool-call-card.js +1046 -0
  59. package/dist/tool-call-card.js.map +1 -0
  60. package/package.json +79 -4
@@ -0,0 +1,175 @@
1
+ const light = { "bg": "#f7f7f7", "surface": "#ffffff", "surface-raised": "#f1f1f1", "border": "#e4e4e4", "border-focus": "#4d9de0", "text": "#18181a", "text-secondary": "#57575d", "text-tertiary": "#68686f", "accent": "#1f6dc2", "accent-hover": "#1a5ca6", "green": "#14783b", "yellow": "#a16207", "red": "#b91c1c", "purple": "#7c3aed", "orange": "#c2410c", "ib-col": "#efefef", "ib-card": "#ffffff", "ib-card-dim": "#f8f8f8", "ib-card-border": "#e3e3e3", "ib-pill": "#e2e2e2", "ib-text": "#161616", "ib-text-2": "#555558", "ib-muted": "#65656b", "ib-seg": "#ebebeb", "ib-seg-on": "#ffffff", "ib-spark": "#5b7fe0", "ib-shadow": "0 1px 2px rgba(0,0,0,0.06)", "ib-shadow-raised": "0 14px 30px rgba(0,0,0,0.14), 0 3px 8px rgba(0,0,0,0.08)", "st-wait": "#c2780a", "st-run": "#2f63e0", "st-done": "#137a3e", "st-fail": "#d43a3a", "st-fail-text": "#c02f2f" };
2
+ const dark = { "bg": "#1c1c1f", "surface": "#232327", "surface-raised": "#2a2a2f", "border": "#34343a", "border-focus": "#4d9de0", "text": "#ededf0", "text-secondary": "#a8a8b0", "text-tertiary": "#93939b", "accent": "#4d9de0", "accent-hover": "#3b82c4", "green": "#3ecf8e", "yellow": "#f6c90e", "red": "#f26b6b", "purple": "#a78bfa", "orange": "#f97316", "ib-col": "#18181b", "ib-card": "#242428", "ib-card-dim": "#1f1f23", "ib-card-border": "#34343a", "ib-pill": "#2f2f35", "ib-text": "#f2f2f3", "ib-text-2": "#b4b4bb", "ib-muted": "#93939b", "ib-seg": "#161619", "ib-seg-on": "#2e2e33", "ib-spark": "#7b9cf0", "ib-shadow": "0 1px 2px rgba(0,0,0,0.35)", "ib-shadow-raised": "0 14px 32px rgba(0,0,0,0.5), 0 3px 8px rgba(0,0,0,0.35)", "st-wait": "#f5a524", "st-run": "#6b93f2", "st-done": "#3fb968", "st-fail": "#f26b6b", "st-fail-text": "#f26b6b" };
3
+ const shared = { "ease": "cubic-bezier(0.2,0.8,0.2,1)", "ease-out": "cubic-bezier(0.23, 1, 0.32, 1)", "ease-in-out": "cubic-bezier(0.77, 0, 0.175, 1)", "dur-press": "160ms", "dur-expand": "240ms", "dur-move": "320ms", "dur-fade": "180ms", "radius": "10px", "font": 'Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Apple SD Gothic Neo", Pretendard, sans-serif', "mono": "'SF Mono', 'Fira Code', ui-monospace, Menlo, monospace" };
4
+ const tokens = {
5
+ light,
6
+ dark,
7
+ shared
8
+ };
9
+ const LIGHT = tokens.light;
10
+ const DARK = tokens.dark;
11
+ const SHARED = tokens.shared;
12
+ function hostVars(set) {
13
+ return Object.entries(set).map(([k, v]) => `--${k}: var(--ui-${k}, ${v});`).join(" ");
14
+ }
15
+ function pageVars(set) {
16
+ return Object.entries(set).map(([k, v]) => `--ui-${k}: ${v};`).join(" ");
17
+ }
18
+ const baseCss = `
19
+ :host { ${hostVars(SHARED)} ${hostVars(LIGHT)}
20
+ display: block; box-sizing: border-box; color: var(--text); font-family: var(--font);
21
+ font-size: 14px; line-height: 1.45; -webkit-font-smoothing: antialiased; color-scheme: light; }
22
+ :host([theme="dark"]) { ${hostVars(DARK)} color-scheme: dark; }
23
+ @media (prefers-color-scheme: dark) { :host(:not([theme="light"])) { ${hostVars(DARK)} color-scheme: dark; } }
24
+ :host([hidden]) { display: none; }
25
+ *, *::before, *::after { box-sizing: border-box; }
26
+ button, input, textarea, select { font: inherit; color: inherit; }
27
+ button { cursor: pointer; }
28
+ :focus { outline: none; }
29
+ :focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
30
+ .sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
31
+ clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
32
+ .mono { font-family: var(--mono); }
33
+ @media (prefers-reduced-motion: reduce) {
34
+ *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;
35
+ transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
36
+ }
37
+ `;
38
+ const tokensCss = `/* @2lab.ai/ui design tokens */
39
+ :root, [data-theme="light"] { ${pageVars(SHARED)} ${pageVars(LIGHT)} color-scheme: light; }
40
+ [data-theme="dark"] { ${pageVars(DARK)} color-scheme: dark; }
41
+ @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { ${pageVars(DARK)} color-scheme: dark; } }
42
+ `;
43
+ class UiElement extends HTMLElement {
44
+ static styles = [];
45
+ root;
46
+ content;
47
+ #data;
48
+ #queued = false;
49
+ #gen = 0;
50
+ constructor() {
51
+ super();
52
+ this.root = this.attachShadow({ mode: "open" });
53
+ const ctor = this.constructor;
54
+ const style = document.createElement("style");
55
+ style.textContent = [baseCss, ...ctor.styles].join("\n");
56
+ this.content = document.createElement("div");
57
+ this.content.setAttribute("part", "root");
58
+ this.content.className = "ui-root";
59
+ this.root.append(style, this.content);
60
+ }
61
+ get data() {
62
+ return this.#data;
63
+ }
64
+ set data(value) {
65
+ this.#data = value;
66
+ this.requestRender();
67
+ }
68
+ connectedCallback() {
69
+ if (Object.hasOwn(this, "data")) {
70
+ const early = this.data;
71
+ delete this.data;
72
+ this.data = early;
73
+ }
74
+ this.requestRender();
75
+ }
76
+ disconnectedCallback() {
77
+ }
78
+ /** Batch renders into one microtask. */
79
+ requestRender() {
80
+ if (this.#queued) return;
81
+ this.#queued = true;
82
+ const gen = this.#gen;
83
+ queueMicrotask(() => {
84
+ if (!this.#queued || gen !== this.#gen) return;
85
+ this.#queued = false;
86
+ if (this.isConnected) this.update();
87
+ });
88
+ }
89
+ /** Render synchronously (tests, or right before measuring). Cancels a queued render. */
90
+ renderNow() {
91
+ this.#queued = false;
92
+ this.#gen++;
93
+ this.update();
94
+ }
95
+ update() {
96
+ const focus = this.#focusState();
97
+ this.content.innerHTML = this.render();
98
+ this.updated();
99
+ if (!focus) return;
100
+ const next = focus.key === void 0 ? void 0 : Array.from(this.content.querySelectorAll("[data-key]")).find(
101
+ (el) => el.dataset.key === focus.key
102
+ );
103
+ (next ?? this.focusFallback())?.focus({ preventScroll: true });
104
+ }
105
+ /** Where focus goes when the focused element is gone after a render (its key no longer rendered). Default: nowhere. */
106
+ focusFallback() {
107
+ return null;
108
+ }
109
+ #focusState() {
110
+ try {
111
+ const active = this.root.activeElement;
112
+ return active && this.content.contains(active) ? { key: active.dataset?.key } : void 0;
113
+ } catch {
114
+ return void 0;
115
+ }
116
+ }
117
+ /** Hook after each render (wire listeners on fresh nodes, start timers). */
118
+ updated() {
119
+ }
120
+ /** Dispatch a bubbling, composed, cancelable event. Returns false when a listener called preventDefault(). */
121
+ emit(name, detail) {
122
+ return this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true, cancelable: true }));
123
+ }
124
+ /** Query inside the shadow root. */
125
+ $(selector) {
126
+ return this.root.querySelector(selector);
127
+ }
128
+ $$(selector) {
129
+ return Array.from(this.root.querySelectorAll(selector));
130
+ }
131
+ }
132
+ function define(tag, ctor) {
133
+ if (typeof customElements !== "undefined" && !customElements.get(tag)) customElements.define(tag, ctor);
134
+ }
135
+ function prefersReducedMotion() {
136
+ return typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
137
+ }
138
+ function esc(value) {
139
+ return String(value ?? "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
140
+ }
141
+ function escAttr(value) {
142
+ return esc(value).replace(/"/g, "&quot;").replace(/'/g, "&#39;");
143
+ }
144
+ const SAFE_SCHEMES = /^(https?:|mailto:)/i;
145
+ function safeHref(url) {
146
+ const s = String(url ?? "").trim();
147
+ return SAFE_SCHEMES.test(s) ? escAttr(s) : "#";
148
+ }
149
+ function cls(...names) {
150
+ return names.filter(Boolean).join(" ");
151
+ }
152
+ function attrs(map) {
153
+ let out = "";
154
+ for (const [k, v] of Object.entries(map)) {
155
+ if (v === false || v === null || v === void 0) continue;
156
+ out += v === true ? ` ${k}` : ` ${k}="${escAttr(v)}"`;
157
+ }
158
+ return out;
159
+ }
160
+ export {
161
+ DARK as D,
162
+ LIGHT as L,
163
+ SHARED as S,
164
+ UiElement as U,
165
+ attrs as a,
166
+ baseCss as b,
167
+ cls as c,
168
+ define as d,
169
+ esc as e,
170
+ escAttr as f,
171
+ prefersReducedMotion as p,
172
+ safeHref as s,
173
+ tokensCss as t
174
+ };
175
+ //# sourceMappingURL=html-elD6Bb_u.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-elD6Bb_u.js","sources":["../src/core/tokens.ts","../src/core/element.ts","../src/core/html.ts"],"sourcesContent":["import tokens from './tokens.json';\n\n/**\n * Design tokens. Inside every component's shadow root the dashboard names (`--text`, `--surface`, `--st-run` …)\n * are defined on `:host` and read the public `--ui-*` property first, so a page themes every component by\n * setting `--ui-text` etc. (or loading `@2lab.ai/ui/tokens.css`). Without any page tokens a component follows\n * `prefers-color-scheme`, and the `theme=\"light|dark\"` attribute pins it.\n */\nexport type TokenSet = Record<string, string>;\nexport const LIGHT: TokenSet = tokens.light;\nexport const DARK: TokenSet = tokens.dark;\nexport const SHARED: TokenSet = tokens.shared;\n\nfunction hostVars(set: TokenSet): string {\n return Object.entries(set)\n .map(([k, v]) => `--${k}: var(--ui-${k}, ${v});`)\n .join(' ');\n}\n\nfunction pageVars(set: TokenSet): string {\n return Object.entries(set)\n .map(([k, v]) => `--ui-${k}: ${v};`)\n .join(' ');\n}\n\n/** Shared stylesheet prepended to every component's shadow root. */\nexport const baseCss = `\n:host { ${hostVars(SHARED)} ${hostVars(LIGHT)}\n display: block; box-sizing: border-box; color: var(--text); font-family: var(--font);\n font-size: 14px; line-height: 1.45; -webkit-font-smoothing: antialiased; color-scheme: light; }\n:host([theme=\"dark\"]) { ${hostVars(DARK)} color-scheme: dark; }\n@media (prefers-color-scheme: dark) { :host(:not([theme=\"light\"])) { ${hostVars(DARK)} color-scheme: dark; } }\n:host([hidden]) { display: none; }\n*, *::before, *::after { box-sizing: border-box; }\nbutton, input, textarea, select { font: inherit; color: inherit; }\nbutton { cursor: pointer; }\n:focus { outline: none; }\n:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }\n.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;\n clip: rect(0 0 0 0); white-space: nowrap; border: 0; }\n.mono { font-family: var(--mono); }\n@media (prefers-reduced-motion: reduce) {\n *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important; scroll-behavior: auto !important; }\n}\n`;\n\n/** Optional page-level tokens (`@2lab.ai/ui/tokens.css`): `data-theme=\"dark|light\"` on any ancestor switches. */\nexport const tokensCss = `/* @2lab.ai/ui design tokens */\n:root, [data-theme=\"light\"] { ${pageVars(SHARED)} ${pageVars(LIGHT)} color-scheme: light; }\n[data-theme=\"dark\"] { ${pageVars(DARK)} color-scheme: dark; }\n@media (prefers-color-scheme: dark) { :root:not([data-theme=\"light\"]) { ${pageVars(DARK)} color-scheme: dark; } }\n`;\n","import { baseCss } from './tokens';\n\n/**\n * Base class for every @2lab.ai/ui component.\n *\n * - Open shadow root with `baseCss` + the subclass's `static styles`.\n * - Data in, events out: set `el.data = {...}` (or the component's own properties) → one batched render;\n * user intent leaves as a bubbling, composed `CustomEvent` (`ui-*`) that the host app handles.\n * - `render()` returns an HTML string; every dynamic value must go through `esc` / `escAttr` / `safeHref`.\n * - Focus survives a re-render when the focused element carries `data-key` (restored to the same key).\n * - Subclasses that tick (timers) should update text nodes in place instead of re-rendering.\n */\nexport abstract class UiElement<D = unknown> extends HTMLElement {\n static styles: string[] = [];\n\n protected readonly root: ShadowRoot;\n protected readonly content: HTMLElement;\n #data: D | undefined;\n #queued = false;\n #gen = 0;\n\n constructor() {\n super();\n this.root = this.attachShadow({ mode: 'open' });\n const ctor = this.constructor as typeof UiElement;\n const style = document.createElement('style');\n style.textContent = [baseCss, ...ctor.styles].join('\\n');\n this.content = document.createElement('div');\n this.content.setAttribute('part', 'root');\n this.content.className = 'ui-root';\n this.root.append(style, this.content);\n }\n\n get data(): D | undefined {\n return this.#data;\n }\n\n set data(value: D | undefined) {\n this.#data = value;\n this.requestRender();\n }\n\n connectedCallback(): void {\n // `data` set before this element was defined (its module loaded after the host's script ran) is an own\n // property that shadows the accessor: move it through the setter. Here, not in the constructor — a subclass\n // setter may use private fields that only exist once construction is done.\n if (Object.hasOwn(this, 'data')) {\n const early = (this as { data?: D }).data;\n delete (this as { data?: D }).data;\n this.data = early;\n }\n this.requestRender();\n }\n\n disconnectedCallback(): void {}\n\n /** Batch renders into one microtask. */\n requestRender(): void {\n if (this.#queued) return;\n this.#queued = true;\n const gen = this.#gen;\n queueMicrotask(() => {\n if (!this.#queued || gen !== this.#gen) return;\n this.#queued = false;\n if (this.isConnected) this.update();\n });\n }\n\n /** Render synchronously (tests, or right before measuring). Cancels a queued render. */\n renderNow(): void {\n this.#queued = false;\n this.#gen++;\n this.update();\n }\n\n protected update(): void {\n const focus = this.#focusState();\n this.content.innerHTML = this.render();\n // After updated(): a subclass may unhide or move what was focused there (a display:none element takes no focus).\n this.updated();\n if (!focus) return;\n // Compare dataset values instead of building a selector: keys may hold any characters.\n const next =\n focus.key === undefined\n ? undefined\n : Array.from(this.content.querySelectorAll<HTMLElement>('[data-key]')).find(\n (el) => el.dataset.key === focus.key,\n );\n (next ?? this.focusFallback())?.focus({ preventScroll: true });\n }\n\n /** Where focus goes when the focused element is gone after a render (its key no longer rendered). Default: nowhere. */\n protected focusFallback(): HTMLElement | null {\n return null;\n }\n\n #focusState(): { key: string | undefined } | undefined {\n try {\n const active = this.root.activeElement as HTMLElement | null;\n return active && this.content.contains(active) ? { key: active.dataset?.key } : undefined;\n } catch {\n return undefined;\n }\n }\n\n /** The component's markup. */\n protected abstract render(): string;\n\n /** Hook after each render (wire listeners on fresh nodes, start timers). */\n protected updated(): void {}\n\n /** Dispatch a bubbling, composed, cancelable event. Returns false when a listener called preventDefault(). */\n protected emit<T>(name: string, detail: T): boolean {\n return this.dispatchEvent(new CustomEvent<T>(name, { detail, bubbles: true, composed: true, cancelable: true }));\n }\n\n /** Query inside the shadow root. */\n protected $<E extends Element = HTMLElement>(selector: string): E | null {\n return this.root.querySelector<E>(selector);\n }\n\n protected $$<E extends Element = HTMLElement>(selector: string): E[] {\n return Array.from(this.root.querySelectorAll<E>(selector));\n }\n}\n\n/** Register a custom element once (safe to import twice). */\nexport function define(tag: string, ctor: CustomElementConstructor): void {\n if (typeof customElements !== 'undefined' && !customElements.get(tag)) customElements.define(tag, ctor);\n}\n\n/** True when the user asked for less motion. */\nexport function prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n","/** HTML-escape text for element content. Every model-, user- or tool-written string goes through this. */\nexport function esc(value: unknown): string {\n return String(value ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/** Escape for a double-quoted attribute value. */\nexport function escAttr(value: unknown): string {\n return esc(value).replace(/\"/g, '&quot;').replace(/'/g, '&#39;');\n}\n\nconst SAFE_SCHEMES = /^(https?:|mailto:)/i;\n\n/** A link target that cannot run script: http(s)/mailto only, otherwise `#`. */\nexport function safeHref(url: unknown): string {\n const s = String(url ?? '').trim();\n return SAFE_SCHEMES.test(s) ? escAttr(s) : '#';\n}\n\n/** Join class names, skipping falsy entries. */\nexport function cls(...names: Array<string | false | null | undefined>): string {\n return names.filter(Boolean).join(' ');\n}\n\n/** `key=\"value\"` pairs for truthy values, escaped. `true` renders a bare boolean attribute. */\nexport function attrs(map: Record<string, string | number | boolean | null | undefined>): string {\n let out = '';\n for (const [k, v] of Object.entries(map)) {\n if (v === false || v === null || v === undefined) continue;\n out += v === true ? ` ${k}` : ` ${k}=\"${escAttr(v)}\"`;\n }\n return out;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @2lab.ai/ui — agent UI Web Components. Importing this module registers every element.
3
+ * Import a single component with `@2lab.ai/ui/<slug>` to register only that one.
4
+ */
5
+ export * from './components/agent-inbox/index.js';
6
+ export * from './components/agent-queue/index.js';
7
+ export * from './components/agent-run/index.js';
8
+ export * from './components/ai-answer/index.js';
9
+ export * from './components/context-window/index.js';
10
+ export * from './components/memory-panel/index.js';
11
+ export * from './components/model-picker/index.js';
12
+ export * from './components/tool-call-card/index.js';
13
+ export { define, prefersReducedMotion, UiElement } from './core/element.js';
14
+ export { clamp, fmtAgo, fmtClock, fmtDuration, fmtInt, fmtTokens, fmtUsd } from './core/format.js';
15
+ export { attrs, cls, esc, escAttr, safeHref } from './core/html.js';
16
+ export { baseCss, DARK, LIGHT, SHARED, tokensCss } from './core/tokens.js';
package/dist/index.js ADDED
@@ -0,0 +1,129 @@
1
+ import { ANNOUNCE_MS, BOARD_HOLD_MS, UiAgentInbox, agentDots, artifactKind, boardCounts, columnsByStatus, holdLanes, placeHolds, statusOf, statusTone } from "./agent-inbox.js";
2
+ import { LOW_PCT, UiAgentQueue, accountState, advanceProvider, axisPos, capacityNews, dayRuns, emptyReturnAt, firstReturn, fmtCount, fmtPct, laneNews, nextRefill, niceMax, normalize, orderJobs, plain, poolState, runBins, runKind, scheduleLabel, timeText, timelineMarks, toMs, upNext } from "./agent-queue.js";
3
+ import { UiAgentRun, runApprovalFields, runChoiceOrder, runDomKey, runFieldText, runFoldedSteps, runNeedsCount, runPlanPhase, runQuestionKey, runTimeOfDay } from "./agent-run.js";
4
+ import { UiAiAnswer, answerCopyText, answerLinkInfo, answerLinkKey, answerLinkify, answerMarkdown, answerTookLabel, renderAnswer } from "./ai-answer.js";
5
+ import { CELLS, UiContextWindow, cellMap, contextLevel, contextParts, markIndex } from "./context-window.js";
6
+ import { FOLD_MS, UNDO_MS, UiMemoryPanel, entryKeys, entryMatches, highlight, isSameEdit, shortText, storeUsed, usageAfterAdd, usageLevel } from "./memory-panel.js";
7
+ import { MODEL_EFFORT_LEVELS, UiModelPicker, anchorMoved, anchorSpot, fmtModelPrice, fmtModelTokens, meterSegments, modelEffortLabel, modelEffortLevels, modelGlyph, modelMeters, placeModelMenu, validModelPrice } from "./model-picker.js";
8
+ import { TOOL_ICONS, UiToolCallCard, UiToolCallGroup, callKeys, formatToolClock, formatToolMs, groupStats, highlightJson, normStatus, toCodeText, toolCallStrings, toolIcon } from "./tool-call-card.js";
9
+ import { D, L, S, U, a, b, c, d, e, f, p, s, t } from "./html-elD6Bb_u.js";
10
+ import { c as c2, f as f2, a as a2, b as b2, d as d2, e as e2, g } from "./format-BBGWXPzk.js";
11
+ export {
12
+ ANNOUNCE_MS,
13
+ BOARD_HOLD_MS,
14
+ CELLS,
15
+ D as DARK,
16
+ FOLD_MS,
17
+ L as LIGHT,
18
+ LOW_PCT,
19
+ MODEL_EFFORT_LEVELS,
20
+ S as SHARED,
21
+ TOOL_ICONS,
22
+ UNDO_MS,
23
+ UiAgentInbox,
24
+ UiAgentQueue,
25
+ UiAgentRun,
26
+ UiAiAnswer,
27
+ UiContextWindow,
28
+ U as UiElement,
29
+ UiMemoryPanel,
30
+ UiModelPicker,
31
+ UiToolCallCard,
32
+ UiToolCallGroup,
33
+ accountState,
34
+ advanceProvider,
35
+ agentDots,
36
+ anchorMoved,
37
+ anchorSpot,
38
+ answerCopyText,
39
+ answerLinkInfo,
40
+ answerLinkKey,
41
+ answerLinkify,
42
+ answerMarkdown,
43
+ answerTookLabel,
44
+ artifactKind,
45
+ a as attrs,
46
+ axisPos,
47
+ b as baseCss,
48
+ boardCounts,
49
+ callKeys,
50
+ capacityNews,
51
+ cellMap,
52
+ c2 as clamp,
53
+ c as cls,
54
+ columnsByStatus,
55
+ contextLevel,
56
+ contextParts,
57
+ dayRuns,
58
+ d as define,
59
+ emptyReturnAt,
60
+ entryKeys,
61
+ entryMatches,
62
+ e as esc,
63
+ f as escAttr,
64
+ firstReturn,
65
+ f2 as fmtAgo,
66
+ a2 as fmtClock,
67
+ fmtCount,
68
+ b2 as fmtDuration,
69
+ d2 as fmtInt,
70
+ fmtModelPrice,
71
+ fmtModelTokens,
72
+ fmtPct,
73
+ e2 as fmtTokens,
74
+ g as fmtUsd,
75
+ formatToolClock,
76
+ formatToolMs,
77
+ groupStats,
78
+ highlight,
79
+ highlightJson,
80
+ holdLanes,
81
+ isSameEdit,
82
+ laneNews,
83
+ markIndex,
84
+ meterSegments,
85
+ modelEffortLabel,
86
+ modelEffortLevels,
87
+ modelGlyph,
88
+ modelMeters,
89
+ nextRefill,
90
+ niceMax,
91
+ normStatus,
92
+ normalize,
93
+ orderJobs,
94
+ placeHolds,
95
+ placeModelMenu,
96
+ plain,
97
+ poolState,
98
+ p as prefersReducedMotion,
99
+ renderAnswer,
100
+ runApprovalFields,
101
+ runBins,
102
+ runChoiceOrder,
103
+ runDomKey,
104
+ runFieldText,
105
+ runFoldedSteps,
106
+ runKind,
107
+ runNeedsCount,
108
+ runPlanPhase,
109
+ runQuestionKey,
110
+ runTimeOfDay,
111
+ s as safeHref,
112
+ scheduleLabel,
113
+ shortText,
114
+ statusOf,
115
+ statusTone,
116
+ storeUsed,
117
+ timeText,
118
+ timelineMarks,
119
+ toCodeText,
120
+ toMs,
121
+ t as tokensCss,
122
+ toolCallStrings,
123
+ toolIcon,
124
+ upNext,
125
+ usageAfterAdd,
126
+ usageLevel,
127
+ validModelPrice
128
+ };
129
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}