@opencxh/domain 1.219.0 → 1.222.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.
@@ -510,6 +510,24 @@ export type ServerOp = {
510
510
  channelId: string;
511
511
  interactionId: string;
512
512
  body: NoteBody;
513
+ }
514
+ /**
515
+ * Put an emoji on a message at the provider, or take it off.
516
+ *
517
+ * Only dispatched to a provider that declares the `message_reactions` feature — everywhere
518
+ * else the reaction stays ours alone, which is the honest outcome for a channel whose
519
+ * protocol has no such thing (mail).
520
+ *
521
+ * `emoji` is the literal character. Providers that speak their own vocabulary translate at
522
+ * their own edge; a reaction means the same thing on every channel and should read the same.
523
+ */
524
+ | {
525
+ kind: "message.react";
526
+ channelId: string;
527
+ activityId: string;
528
+ emoji: string;
529
+ /** `true` sets it, `false` removes it. */
530
+ on: boolean;
513
531
  } | {
514
532
  kind: "message.forward";
515
533
  channelId: string;
@@ -640,6 +658,13 @@ export declare const FEATURE_FOLDER_MANAGEMENT = "folder_management";
640
658
  * channels in `GET /search/sources`; the client fans out via `POST /search/mailbox`.
641
659
  */
642
660
  export declare const FEATURE_REMOTE_SEARCH = "remote_search";
661
+ /**
662
+ * Well-known `ProviderFeature.name` for per-message emoji reactions. A provider that can both
663
+ * report the reactions on a message and set one on the user's behalf declares it true; the
664
+ * comm-server then dispatches `message.react` there. Everywhere else the reaction is ours
665
+ * alone, which is the honest outcome for a protocol that has no such thing (mail).
666
+ */
667
+ export declare const FEATURE_MESSAGE_REACTIONS = "message_reactions";
643
668
  /**
644
669
  * Result shape for `IProvider.dispatch` and the comm-server
645
670
  * `dispatchToProvider` helper, discriminated on `ok`. Deliberately not
@@ -0,0 +1,6 @@
1
+ import { DocumentOperationDescriptor } from './documents';
2
+ export declare const DOCUMENT_OPERATIONS: DocumentOperationDescriptor[];
3
+ /** The descriptors valid on one kind. Used by an adapter to declare, and by the guard to refuse. */
4
+ export declare function operationsForKind(kind: string): DocumentOperationDescriptor[];
5
+ /** One descriptor by name, or `undefined` for an operation nobody declares. */
6
+ export declare function operationDescriptor(op: string): DocumentOperationDescriptor | undefined;
@@ -0,0 +1,151 @@
1
+ import { AiToolParameterSchema } from './ai-tools';
2
+ /**
3
+ * Open editors, readable and drivable across app boundaries.
4
+ *
5
+ * An app that mounts an editor (Univer, pdf.js, a block editor) holds a live document model no
6
+ * other layer can reach. The assistant beside it could neither read it nor change it, so every
7
+ * "what does this say" and "fix that cell" ended at the app boundary.
8
+ *
9
+ * Three keys, all through `sdk.services.execute`, mirroring `resources.*`:
10
+ *
11
+ * | Key | Params | Answer |
12
+ * |---|---|---|
13
+ * | `documents.describe` | {@link DocumentTargetParams} | {@link DocumentCapability} \| `null` |
14
+ * | `documents.inspect` | {@link DocumentInspectParams} | {@link DocumentInspection} \| `null` |
15
+ * | `documents.apply` | {@link DocumentApplyParams} | {@link DocumentApplyResult} \| `null` |
16
+ *
17
+ * A service-bus contract rather than a provider role, for the same reason as `resources.*`: the
18
+ * document only exists in the browser of the user who has it open. There is nothing on the server
19
+ * to ask.
20
+ *
21
+ * **What a server-side AI tool can and cannot do with this.** The tool loop runs on the server and
22
+ * the transport is one-way (`Bridge.sse.push` → the app's SSE handler; handler return values are
23
+ * discarded in `packages/app-sdk/src/modules/api.ts`). So a tool can *deliver* operations and must
24
+ * say so honestly; it cannot read an answer back. Reading therefore travels the other way, as
25
+ * `context.collect` slices that ride the next turn — which doubles as the feedback channel for an
26
+ * operation delivered a turn earlier. {@link DocumentApplyResult} is already shaped as the answer
27
+ * a round trip would return, so adding one later is transport work and not a contract change.
28
+ */
29
+ /** The service-bus keys, as constants so a typo does not silently yield an empty list. */
30
+ export declare const DOCUMENT_DESCRIBE_SERVICE = "documents.describe";
31
+ export declare const DOCUMENT_INSPECT_SERVICE = "documents.inspect";
32
+ export declare const DOCUMENT_APPLY_SERVICE = "documents.apply";
33
+ /**
34
+ * Which document, as `<kind>:<ref>` — `file:<fileId>` for a stored file.
35
+ *
36
+ * Deliberately the same shape as a scopeKey and not a second identifier: it is the key the
37
+ * assistant already groups its conversations on and the key `provider/scope/authorize` gates, so
38
+ * "the document the user is looking at" and "the scope this thread belongs to" stay one thing.
39
+ */
40
+ export type DocumentKey = string;
41
+ /** Params for `documents.describe` and the shared prefix of the other two. */
42
+ export interface DocumentTargetParams {
43
+ docKey: DocumentKey;
44
+ }
45
+ /**
46
+ * One operation an editor accepts, as the editor itself declares it.
47
+ *
48
+ * Declared rather than derived: the same list feeds the AI tool's parameter schema and the
49
+ * adapter's own validation, so the model can never be offered an operation the editor does not
50
+ * implement. Adding a capability is one descriptor plus one handler — no new tool, no prompt
51
+ * change, no server change.
52
+ */
53
+ export interface DocumentOperationDescriptor {
54
+ /** `<kind>.<verb>`, and the prefix *is* the kind: that makes the guard a prefix test. */
55
+ op: string;
56
+ /** The document kinds this operation is valid on. */
57
+ kinds: string[];
58
+ /** One line, model-facing. This is what the assistant reads to choose. */
59
+ summary: string;
60
+ parameters: AiToolParameterSchema;
61
+ /**
62
+ * Can the user undo it with ctrl-Z?
63
+ *
64
+ * Not cosmetic: a Univer facade call goes through the command service and lands in the undo
65
+ * stack, while a snapshot rewrite (slides has no facade at all) does not. The tool result says
66
+ * which, because "I changed it, undo if you disagree" is a promise that has to hold.
67
+ */
68
+ undoable: boolean;
69
+ /**
70
+ * Does the user see the change before saving?
71
+ *
72
+ * `false` means the operation is written on save but not drawn yet — pdf.js draws its editor
73
+ * layer from `AnnotationEditor` instances, so an annotation injected as a plain object into the
74
+ * annotation storage is real to `saveDocument()` and invisible on screen. An invisible change
75
+ * needs to be announced, not assumed.
76
+ */
77
+ visible: boolean;
78
+ }
79
+ /** Answer to `documents.describe`: what is open, and what may be done to it. */
80
+ export interface DocumentCapability {
81
+ docKey: DocumentKey;
82
+ /** `pdf` · `sheet` · `word` · `slides`, or whatever a future editor calls itself. */
83
+ kind: string;
84
+ title: string;
85
+ /** Someone else holds the lock, or a write-back would drop content, or it is read-only. */
86
+ readOnly: boolean;
87
+ /**
88
+ * Is the document parsed and answerable, or still loading?
89
+ *
90
+ * A separate field because the page knows what the file *is* (name, kind, which operations
91
+ * apply) the moment it opens, while the engine needs a second or two to parse it. Without the
92
+ * distinction a consumer cannot tell "no content" from "not yet", and a model told the first
93
+ * reports an empty document.
94
+ */
95
+ ready: boolean;
96
+ /** What a write-back would lose, from the editor's own `unsupportedFeatures`. */
97
+ blocked: string[];
98
+ /** The subset of {@link DOCUMENT_OPERATIONS} this mounted editor actually implements. */
99
+ operations: DocumentOperationDescriptor[];
100
+ }
101
+ /** One operation to apply. The extra keys are the params its descriptor declares. */
102
+ export interface DocumentOperation {
103
+ op: string;
104
+ [key: string]: unknown;
105
+ }
106
+ export interface DocumentApplyParams extends DocumentTargetParams {
107
+ operations: DocumentOperation[];
108
+ }
109
+ /**
110
+ * What applying did. Partial success is the normal case, not an edge: operations arrive as a batch
111
+ * from a model, and one bad range should not discard the other four.
112
+ */
113
+ export interface DocumentApplyResult {
114
+ docKey: DocumentKey;
115
+ applied: number;
116
+ failed: {
117
+ op: string;
118
+ reason: string;
119
+ }[];
120
+ /** Is there unsaved work now? The user still owns the save. */
121
+ dirty: boolean;
122
+ /** How many applied operations are not drawn yet. See {@link DocumentOperationDescriptor.visible}. */
123
+ pending: number;
124
+ }
125
+ /**
126
+ * What to read. Absent `slices` = the cheap overview only.
127
+ *
128
+ * Deliberately not the typed per-kind query tree Univer's inspection API uses: the consumer here
129
+ * is a prompt with a character budget, and the useful question is always "the overview, plus this
130
+ * much content". Names are per kind and documented by the adapter's own descriptor.
131
+ */
132
+ export interface DocumentInspectParams extends DocumentTargetParams {
133
+ slices?: string[];
134
+ /** Character ceiling per slice. The adapter truncates predictably rather than mid-row. */
135
+ budget?: number;
136
+ }
137
+ /** Answer to `documents.inspect`: read-only, kind-shaped, budgeted. */
138
+ export interface DocumentInspection {
139
+ docKey: DocumentKey;
140
+ kind: string;
141
+ /** Per-slice content, already truncated. `truncated` names the slices that were cut. */
142
+ slices: Record<string, unknown>;
143
+ truncated?: string[];
144
+ }
145
+ /**
146
+ * The kind out of a {@link DocumentKey} or an operation name.
147
+ *
148
+ * One helper for both because the operation prefix *is* the kind — `pdf.goToPage` on a `sheet`
149
+ * is a routing mistake, and this is what catches it.
150
+ */
151
+ export declare function documentKindOf(value: string): string;
@@ -18,7 +18,7 @@ export declare const APP_PERMISSIONS: {
18
18
  readonly "app-store": readonly ["app.publish", "app.read", "app.write", "setting.read", "setting.write"];
19
19
  readonly assist: readonly ["board.read"];
20
20
  readonly automations: readonly ["sync.read", "sync.write", "webhook.read", "webhook.write"];
21
- readonly communication: readonly ["account.read", "account.write", "activity-type.read", "activity.read", "activity.write", "attachment.read", "attribute.read", "attribute.write", "calendar.read", "calendar.write", "channel.read", "channel.write", "custom-field.read", "custom-field.write", "folder.read", "folder.write", "inbox.read", "inbox.write", "interaction.read", "interaction.write", "reminder.read", "template.read", "template.write", "topic.read", "topic.write"];
21
+ readonly communication: readonly ["account.read", "account.write", "activity-type.read", "activity.read", "activity.write", "attachment.read", "attribute.read", "attribute.write", "calendar.read", "calendar.write", "channel.read", "channel.write", "custom-field.read", "custom-field.write", "folder.read", "folder.write", "inbox.read", "inbox.write", "interaction.read", "interaction.write", "reaction.read", "reaction.write", "reminder.read", "template.read", "template.write", "topic.read", "topic.write"];
22
22
  readonly context: readonly ["kind.read", "kind.write", "memory.read", "memory.write"];
23
23
  readonly crm: readonly ["company.read", "company.write", "contact.read", "contact.write"];
24
24
  readonly "eylo-voip": readonly ["account.read", "account.write", "callflow.read", "callflow.write", "channel.read", "channel.write", "contact.read", "contact.write", "device.read", "device.write", "group.read", "group.write", "interaction.read", "interaction.write", "media.read", "media.write", "menu.read", "menu.write", "phone-number.read", "phone-number.write", "recording.read", "recording.write", "sip.read", "temporal-rule.read", "temporal-rule.write", "user.read", "user.write", "vmbox.read", "vmbox.write", "webhook.read", "webhook.write"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencxh/domain",
3
- "version": "1.219.0",
3
+ "version": "1.222.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",