@ahmedramez-org/nexus-chat 1.0.0-beta.16 → 1.0.0-beta.17

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.
@@ -267,8 +267,13 @@ export async function checkHostContract(options, checkOptions = {}) {
267
267
  });
268
268
  ensure(new Set(kinds).size === kinds.length, 'a context kind is listed twice (a source replaces its bare kind: list only the source).');
269
269
  });
270
- await checks.run('chat.triggers', 'each trigger is @ or # with a search', () => {
270
+ await checks.run('chat.triggers', 'each trigger is a bare @ or #, or one with a search', () => {
271
271
  const chars = (chat?.triggers ?? []).map((trigger) => {
272
+ if (typeof trigger === 'string') {
273
+ ensure(TRIGGER_CHARS.includes(trigger), `unknown trigger ${JSON.stringify(trigger)}; a bare string is one of: ${TRIGGER_CHARS.join(', ')}.`);
274
+ ensure(connection?.incortaApi?.type === 'bff', `the bare ${trigger} trigger needs a connection.incortaApi of type 'bff'.`);
275
+ return trigger;
276
+ }
272
277
  ensure(TRIGGER_CHARS.includes(trigger.char), `unknown trigger ${JSON.stringify(trigger.char)}.`);
273
278
  ensure(typeof trigger.search === 'function', `the ${trigger.char} trigger has no search().`);
274
279
  return trigger.char;
@@ -133,15 +133,18 @@ export interface ValueMatch {
133
133
  dataType?: string;
134
134
  complete?: boolean;
135
135
  }
136
+ /** The composer trigger characters the chat can serve itself. */
137
+ export declare const BUILT_IN_TRIGGERS: readonly ["@", "#"];
138
+ export type BuiltInTrigger = (typeof BUILT_IN_TRIGGERS)[number];
136
139
  /**
137
- * A composer trigger character. Both search inside the one attached business
138
- * view (`viewId` is that context's `id`); with none or several attached the
139
- * character stays plain text.
140
+ * A composer trigger the host serves. Both search inside the one attached
141
+ * business view (`viewId` is that context's `id`); with none or several
142
+ * attached the character stays plain text.
140
143
  *
141
144
  * - `@` mentions a column. Asked once per view; the chat filters as you type.
142
145
  * - `#` searches the view's values for the typed text.
143
146
  */
144
- export type TriggerSpec = {
147
+ export type TriggerSource = {
145
148
  char: '@';
146
149
  search(request: {
147
150
  viewId: string;
@@ -154,6 +157,21 @@ export type TriggerSpec = {
154
157
  limit: number;
155
158
  }, signal: AbortSignal): Promise<readonly ValueMatch[]>;
156
159
  };
160
+ /**
161
+ * One composer trigger; `chat.triggers` lists them.
162
+ *
163
+ * - A bare `'@'` or `'#'`: the chat serves it itself through a BFF
164
+ * `connection.incortaApi`, across every attached business view and physical
165
+ * table. The user can narrow to one view, then one column, and `#` searches
166
+ * text columns only. Without a BFF `incortaApi` the character is left out
167
+ * with a console warning.
168
+ * - A `TriggerSource`: the host serves it, for one attached view.
169
+ *
170
+ * List each character once. Migrating: code that read `trigger.char` must
171
+ * narrow with `typeof trigger === 'string'` first. Pass bare characters only
172
+ * to a chat that has them (this release or later): an older chat ignores them.
173
+ */
174
+ export type TriggerSpec = BuiltInTrigger | TriggerSource;
157
175
  /** Switches for things the chat builds itself. Each one defaults to `true`. */
158
176
  export interface NexusChatFeatures {
159
177
  /**
package/contract/index.js CHANGED
@@ -11,6 +11,8 @@ export const BUILT_IN_CONTEXT_KINDS = [
11
11
  'ai-container',
12
12
  'knowledge-store',
13
13
  ];
14
+ /** The composer trigger characters the chat can serve itself. */
15
+ export const BUILT_IN_TRIGGERS = ['@', '#'];
14
16
  /**
15
17
  * Reads the namespaced-kind convention. Returns null for bare legacy kinds.
16
18
  * Framework-free on purpose: hosts use this inside `canRender` to route by
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ahmedramez-org/nexus-chat",
3
- "version": "1.0.0-beta.16",
3
+ "version": "1.0.0-beta.17",
4
4
  "description": "NexusChat for any app: a connector and React component that load the prebuilt chat from IncortaCopilot (or a pinned copy), and the host contract types and checks.",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
package/react.js CHANGED
@@ -304,7 +304,7 @@ function EmbeddedChat({ embedUrl, modes, defaultMode, theme = 'light', locale })
304
304
  ref: frame,
305
305
  title: NAME,
306
306
  src,
307
- allow: 'storage-access; microphone',
307
+ allow: 'storage-access; microphone; clipboard-write',
308
308
  style: { display: 'block', width: '100%', height: '100%', border: 0 },
309
309
  }),
310
310
  ),
package/window.js CHANGED
@@ -357,7 +357,7 @@ export function createEmbeddedChat({
357
357
  if (embedded || !win.opened) return;
358
358
  const iframe = document.createElement('iframe');
359
359
  iframe.title = NAME;
360
- iframe.allow = 'storage-access; microphone';
360
+ iframe.allow = 'storage-access; microphone; clipboard-write';
361
361
  iframe.src = embedSrc(embedUrl, theme, locale);
362
362
  iframe.style.cssText = 'display:block;width:100%;height:100%;border:0';
363
363
  win.panel.prepend(iframe);