@opencxh/domain 1.172.1 → 1.173.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/dist/entities/activity/blocks.d.ts +30 -30
- package/dist/entities/activity/catalog.d.ts +63 -86
- package/dist/entities/activity/descriptor.d.ts +31 -32
- package/dist/entities/activity/index.d.ts +2 -2
- package/dist/entities/activity/preview.d.ts +7 -7
- package/dist/entities/activity/resolve.d.ts +37 -38
- package/dist/entities/activity/types.d.ts +64 -35
- package/dist/entities/ai-account/types.d.ts +3 -3
- package/dist/entities/ai-account/vendors.d.ts +25 -32
- package/dist/entities/ai-budget/types.d.ts +5 -5
- package/dist/entities/ai-conversation/types.d.ts +12 -12
- package/dist/entities/ai-profile/types.d.ts +14 -21
- package/dist/entities/ai-settings/types.d.ts +12 -13
- package/dist/entities/analytics/index.d.ts +4 -4
- package/dist/entities/analytics/source.d.ts +1 -1
- package/dist/entities/analytics/usage.d.ts +23 -28
- package/dist/entities/artifact/blocks.d.ts +54 -69
- package/dist/entities/artifact/markdown.d.ts +2 -3
- package/dist/entities/artifact/types.d.ts +46 -54
- package/dist/entities/assignment/types.d.ts +76 -90
- package/dist/entities/channel/index.d.ts +1 -1
- package/dist/entities/channel/signature.d.ts +8 -9
- package/dist/entities/communication/index.d.ts +1 -1
- package/dist/entities/contact/index.d.ts +1 -1
- package/dist/entities/custom-field-def/types.d.ts +14 -14
- package/dist/entities/external-identity/types.d.ts +45 -50
- package/dist/entities/interaction/index.d.ts +1 -1
- package/dist/entities/interaction/types.d.ts +44 -47
- package/dist/entities/live-lens/types.d.ts +39 -44
- package/dist/entities/mcp/types.d.ts +53 -57
- package/dist/entities/memory/alias.d.ts +7 -7
- package/dist/entities/memory/browse.d.ts +21 -21
- package/dist/entities/memory/ingest.d.ts +24 -28
- package/dist/entities/memory/item.d.ts +53 -58
- package/dist/entities/memory/kind.d.ts +25 -25
- package/dist/entities/memory/query.d.ts +49 -51
- package/dist/entities/playbook/actor.d.ts +17 -17
- package/dist/entities/playbook/assignment.d.ts +54 -63
- package/dist/entities/playbook/index.d.ts +2 -2
- package/dist/entities/playbook/labels.d.ts +4 -4
- package/dist/entities/playbook/trigger-vars.d.ts +17 -15
- package/dist/entities/playbook/types.d.ts +174 -303
- package/dist/entities/resource-reminder/types.d.ts +8 -9
- package/dist/entities/time-entry/duration.d.ts +11 -11
- package/dist/entities/time-entry/types.d.ts +59 -59
- package/dist/entities/time-entry/work-type.d.ts +21 -24
- package/dist/entities/topic/examples.d.ts +26 -27
- package/dist/entities/topic/scope.d.ts +11 -12
- package/dist/entities/topic/types.d.ts +26 -28
- package/dist/entities/user/types.d.ts +24 -28
- package/dist/entities/webhook/types.d.ts +6 -6
- package/dist/entities/work/activity.d.ts +36 -0
- package/dist/entities/work/index.d.ts +1 -0
- package/dist/entities/work/keys.d.ts +25 -26
- package/dist/entities/work/ladder.d.ts +48 -52
- package/dist/entities/work/types.d.ts +108 -114
- package/dist/index.cjs +6 -6
- package/dist/index.d.ts +29 -28
- package/dist/index.js +1416 -1258
- package/dist/platform/account.d.ts +34 -38
- package/dist/platform/ai-tools.d.ts +48 -52
- package/dist/platform/api.d.ts +9 -10
- package/dist/platform/author.d.ts +7 -9
- package/dist/platform/capabilities.d.ts +3 -3
- package/dist/platform/communication.d.ts +163 -204
- package/dist/platform/context.d.ts +8 -8
- package/dist/platform/identity.d.ts +16 -19
- package/dist/platform/kernel.d.ts +1 -1
- package/dist/platform/manifest.d.ts +2 -2
- package/dist/platform/media.d.ts +13 -15
- package/dist/platform/permission.d.ts +39 -0
- package/dist/platform/permission.test.d.ts +1 -0
- package/dist/platform/presence.d.ts +30 -30
- package/dist/platform/provider.d.ts +14 -15
- package/dist/platform/resource-source.d.ts +43 -45
- package/dist/platform/resource.d.ts +17 -23
- package/dist/platform/scope.d.ts +35 -61
- package/dist/platform/services.d.ts +4 -4
- package/dist/platform/storage.d.ts +1 -1
- package/dist/platform/sync-source.d.ts +196 -216
- package/dist/platform/transcript-cadence.d.ts +37 -41
- package/dist/platform/ui.d.ts +6 -6
- package/dist/text/endpoint.d.ts +11 -27
- package/package.json +3 -2
|
@@ -2,26 +2,26 @@ import { InteractionParticipant } from '../../platform/communication';
|
|
|
2
2
|
import { ActivityType, InteractionStatus } from '../activity/types';
|
|
3
3
|
export interface ActivityPreview {
|
|
4
4
|
activityId: string;
|
|
5
|
-
/**
|
|
5
|
+
/** Also an app-declared type; the union only keeps the autocomplete. */
|
|
6
6
|
type: ActivityType | (string & {});
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* The line as the server could build it. For built-in types this is the text itself; for a
|
|
9
|
+
* declared type the already-resolved version in the org language.
|
|
10
10
|
*
|
|
11
|
-
* Server
|
|
12
|
-
*
|
|
11
|
+
* Server consumers (search, assistant, analytics) have no user language and read this field.
|
|
12
|
+
* The client prefers {@link snippetKey}.
|
|
13
13
|
*/
|
|
14
14
|
snippet: string;
|
|
15
15
|
authorName: string;
|
|
16
16
|
direction: "inbound" | "outbound" | "internal" | "none";
|
|
17
17
|
createdAt: number;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
19
|
+
* Translation key plus already-extracted parameters, for types that declared one.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
21
|
+
* The preview is computed and stored once on the server, but every reader has their own
|
|
22
|
+
* language. Keeping the key instead of only the sentence lets the inbox list draw it in the
|
|
23
|
+
* viewer's language. (The built-in snippets are still hardcoded Dutch — the same construction
|
|
24
|
+
* fixes that later.)
|
|
25
25
|
*/
|
|
26
26
|
snippetKey?: string;
|
|
27
27
|
snippetParams?: Record<string, string>;
|
|
@@ -70,49 +70,47 @@ export interface Interaction {
|
|
|
70
70
|
assignedTopicId?: string;
|
|
71
71
|
channelId?: string;
|
|
72
72
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* `channel.addressUri`.
|
|
73
|
+
* Derived match key `<scheme>:<resource>` of the channel address. Stable across a channel relink
|
|
74
|
+
* (new channelId, same address), so the link with the channel is not lost. Derived server-side
|
|
75
|
+
* from `channel.addressUri`.
|
|
77
76
|
*/
|
|
78
77
|
channelUriKey?: string;
|
|
79
78
|
title: string;
|
|
80
|
-
/**
|
|
81
|
-
*
|
|
79
|
+
/** One definition, shared with `INTERACTION_STATUS_CHANGED`, so the timeline can record every
|
|
80
|
+
* transition this field can make. */
|
|
82
81
|
status: InteractionStatus;
|
|
83
82
|
/**
|
|
84
|
-
* UX
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
83
|
+
* UX shape of the interaction. "thread" = email style with separately replyable messages (inline
|
|
84
|
+
* reply per activity). "conversation" = chat style with a continuous stream and one bottom
|
|
85
|
+
* composer. The backend may set this; when absent the frontend derives it from
|
|
86
|
+
* `remoteParty.scheme`.
|
|
88
87
|
*/
|
|
89
88
|
shape?: "thread" | "conversation";
|
|
90
89
|
priority: "urgent" | "high" | "normal" | "low";
|
|
91
90
|
/**
|
|
92
|
-
* "Headline"
|
|
93
|
-
*
|
|
91
|
+
* "Headline" counterparty — for 1-1 (mail/sms/direct chat) the only counterparty; for group
|
|
92
|
+
* chats and meetings the group or meeting Uri.
|
|
94
93
|
*/
|
|
95
94
|
remoteParty: InteractionParticipant;
|
|
96
95
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
* `
|
|
100
|
-
*
|
|
96
|
+
* Every participant except our own channel. Optional for backward compatibility with existing
|
|
97
|
+
* interactions; for 1-1 it may be empty or `[remoteParty]` (the UI falls back to
|
|
98
|
+
* `remoteParty`). For group chats and meetings the full list here, roles included
|
|
99
|
+
* (cc/bcc/organizer/…).
|
|
101
100
|
*/
|
|
102
101
|
participants?: InteractionParticipant[];
|
|
103
102
|
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
103
|
+
* Canonical identity keys of the counterparty — the other half of `channelUriKey`, which
|
|
104
|
+
* canonicalizes our own side. Indexed, so "every conversation with this address, this number or
|
|
105
|
+
* this domain" is an index question and not a scan.
|
|
107
106
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* koppeling expliciet heeft gelegd.
|
|
107
|
+
* Holds `mailto:`/`tel:` keys, a `domain:<registrable>` pseudo key for non-public email domains,
|
|
108
|
+
* and `company:<id>`/`contact:<id>` when a person made a link explicitly.
|
|
111
109
|
*
|
|
112
|
-
* **
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
110
|
+
* **A key never becomes false.** "This address appeared in this conversation" always keeps
|
|
111
|
+
* holding, whereas a derived `companyId` becomes false as soon as someone creates, merges or
|
|
112
|
+
* corrects a company — and would then demand a backfill. Resolve an identity to its keys at read
|
|
113
|
+
* time and the answer also covers conversations from before that identity existed.
|
|
116
114
|
*/
|
|
117
115
|
partyKeys?: string[];
|
|
118
116
|
source?: InteractionSource;
|
|
@@ -129,16 +127,15 @@ export interface Interaction {
|
|
|
129
127
|
lastActivityAt?: number;
|
|
130
128
|
lastActivityPreview?: ActivityPreview;
|
|
131
129
|
/**
|
|
132
|
-
* Epoch
|
|
133
|
-
* `applyActivityToInteraction`
|
|
134
|
-
* analytics
|
|
130
|
+
* Epoch ms of the first outgoing reply to this interaction. Set once by
|
|
131
|
+
* `applyActivityToInteraction` on the first outbound activity; drives the first-response-time
|
|
132
|
+
* analytics metric (firstResponseAt - createdAt). Absent = no reply yet.
|
|
135
133
|
*/
|
|
136
134
|
firstResponseAt?: number;
|
|
137
135
|
/**
|
|
138
|
-
* Provider-side folder
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
* niet in een specifieke folder (of provider zonder folder-capability).
|
|
136
|
+
* Provider-side folder this thread is archived under (mail). Set by the sync (folder membership
|
|
137
|
+
* of already-engaged threads) and by `folder.move`. Drives the Folders nav filter and the two-way
|
|
138
|
+
* move. Absent = not in a specific folder (or a provider without folder capability).
|
|
142
139
|
*/
|
|
143
140
|
folderRef?: {
|
|
144
141
|
channelId: string;
|
|
@@ -146,10 +143,10 @@ export interface Interaction {
|
|
|
146
143
|
name: string;
|
|
147
144
|
};
|
|
148
145
|
/**
|
|
149
|
-
* Epoch
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
146
|
+
* Epoch ms until which the interaction is snoozed. While `snoozedTill > now` the interaction is
|
|
147
|
+
* filtered out of the list (its status is then "snoozed"). A cron job wakes expired snoozes: sets
|
|
148
|
+
* status back to "open", bumps `lastActivityAt` and clears `snoozedTill` (to null). `null`/absent
|
|
149
|
+
* = not snoozed.
|
|
153
150
|
*/
|
|
154
151
|
snoozedTill?: number | null;
|
|
155
152
|
}
|
|
@@ -1,79 +1,74 @@
|
|
|
1
|
-
import { OwnerScope } from '../scope/types';
|
|
2
1
|
import { ConditionStep, ForEachStep, LookupStep, ParallelStep, Step } from '../playbook/types';
|
|
2
|
+
import { OwnerScope } from '../scope/types';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* **Waarom dit een eigen entity is en geen playbook met een `stream`-trigger.** Dat was het:
|
|
7
|
-
* `PlaybookTrigger` had een arm `{ kind: "stream" }` met opzet zonder velden, en zo'n rij deed
|
|
8
|
-
* daarna niets van wat een playbook doet — geen run, geen job, geen lock, geen goedkeuringspoort,
|
|
9
|
-
* geen `finalizeRun`. `live-assist` bouwde met de hand een `RunContext` en riep `executeFlow`
|
|
10
|
-
* direct aan.
|
|
4
|
+
* A **read lane**: what listens along during a live conversation, and who it shows something to.
|
|
11
5
|
*
|
|
12
|
-
*
|
|
13
|
-
* `
|
|
14
|
-
*
|
|
15
|
-
* automatisering of naar een leesbaan keek, met twee functies in domain als vangnet en een
|
|
16
|
-
* tabel-scan-plus-cache als selectie.
|
|
6
|
+
* **Why this is its own entity and not a playbook with a `stream` trigger.** It used to be one:
|
|
7
|
+
* `PlaybookTrigger` had a deliberately field-less `{ kind: "stream" }` arm, and such a row then did
|
|
8
|
+
* none of what a playbook does — no run, no job, no lock, no approval gate, no `finalizeRun`.
|
|
17
9
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
10
|
+
* The price was in the fields: `autonomy`, `agentId`, `procedure`, `stats`, `lastRunAt` and
|
|
11
|
+
* `debounceMs` were all meaningless for such a row, and `steps` could hold only four of the ten
|
|
12
|
+
* step types. Every reader of `Playbook` had to implicitly know whether it was looking at an
|
|
13
|
+
* automation or at a read lane.
|
|
20
14
|
*
|
|
21
|
-
*
|
|
15
|
+
* Definitions belong separated by their **runtime**, not by their editor. A read lane has no run,
|
|
16
|
+
* so it is not a playbook. What it shares with a playbook is the **step language** and the
|
|
17
|
+
* executor — not the table.
|
|
22
18
|
*/
|
|
23
19
|
/**
|
|
24
|
-
*
|
|
20
|
+
* What a read lane may do: look up, choose, and do so in parallel or per item if needed.
|
|
25
21
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* hervatten.
|
|
22
|
+
* This is a **real subtype** of {@link Step} and not a list of allowed names. Anything that writes
|
|
23
|
+
* (`action`), costs a model call (`classify`, `generate`, `agent`) or can pause (`wait-for-*`) is
|
|
24
|
+
* outside it — and pausing cannot work here anyway, because there is no row to resume on.
|
|
30
25
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
26
|
+
* That it is a type and not a check is the win: a read lane that would write is now a type error
|
|
27
|
+
* while building, instead of a validation speaking up at save time (or worse: on the first round,
|
|
28
|
+
* during a phone call).
|
|
34
29
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
30
|
+
* Anyone who *does* want something written during a call uses a playbook on an `activity` trigger.
|
|
31
|
+
* That one has a run, an owner and an approval gate.
|
|
37
32
|
*/
|
|
38
33
|
export type ReadStep = LookupStep | ConditionStep | ForEachStep<ReadStep> | ParallelStep<ReadStep>;
|
|
39
|
-
/**
|
|
34
|
+
/** The step types a read lane may hold — the runtime counterpart of {@link ReadStep}. */
|
|
40
35
|
export declare const READ_STEP_TYPES: readonly string[];
|
|
41
36
|
export interface LiveLens {
|
|
42
37
|
id: string;
|
|
43
38
|
organizationId: string;
|
|
44
|
-
/**
|
|
39
|
+
/** Who this lane runs for. The work mode selects the team lanes; see {@link selectLenses}. */
|
|
45
40
|
ownerScope: OwnerScope;
|
|
46
41
|
name: string;
|
|
47
42
|
description?: string;
|
|
48
43
|
enabled: boolean;
|
|
49
|
-
/**
|
|
44
|
+
/** What gets looked up. Read-only — see {@link ReadStep}. */
|
|
50
45
|
steps: ReadStep[];
|
|
51
46
|
createdBy: string;
|
|
52
47
|
}
|
|
53
48
|
/**
|
|
54
|
-
*
|
|
49
|
+
* Why this step list may not be a read lane, or `null` when it may.
|
|
55
50
|
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
51
|
+
* Needed despite {@link ReadStep}, because a `POST` delivers JSON and a type does not help there:
|
|
52
|
+
* this is the gate at **save** time. It used to run on *every* round, every eight seconds per live
|
|
53
|
+
* call, to check a property that was already settled at save time.
|
|
59
54
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
55
|
+
* A reason and not a boolean, because a refused lane otherwise silently does nothing — exactly the
|
|
56
|
+
* class of bug that makes "I switched it on and nothing comes" unanswerable.
|
|
62
57
|
*/
|
|
63
58
|
export declare function readStepError(steps: readonly Step[]): string | null;
|
|
64
59
|
/**
|
|
65
|
-
*
|
|
60
|
+
* The read lanes belonging to *this* agent at *this* moment.
|
|
66
61
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
62
|
+
* The work mode is what selects a team lane: without that choice, someone in both Sales and
|
|
63
|
+
* Support would have both lane sets listening at once — the problem the work mode exists for.
|
|
64
|
+
* Personal and org-wide lanes are independent of it.
|
|
70
65
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
66
|
+
* Note that the *acting identity* of a round is always the agent themselves, also for a team or
|
|
67
|
+
* org-wide lane: during their own call they never see more than they may see. The owner only
|
|
68
|
+
* decides *which* lanes run.
|
|
74
69
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
70
|
+
* No `skipped` outcome any more: that existed to report a lane not allowed to listen, which can no
|
|
71
|
+
* longer exist — `readStepError` refuses it at save time.
|
|
77
72
|
*/
|
|
78
73
|
export declare function selectLenses<T extends Pick<LiveLens, "enabled" | "ownerScope">>(lenses: readonly T[], lens: {
|
|
79
74
|
userId: string;
|
|
@@ -1,40 +1,39 @@
|
|
|
1
1
|
/** How the AI server authenticates to an MCP server. */
|
|
2
2
|
export type McpAuthMode = "header" | "oauth";
|
|
3
3
|
/**
|
|
4
|
-
* @deprecated
|
|
5
|
-
*
|
|
4
|
+
* @deprecated Use {@link McpCredentialScope}. Stays one release because existing rows carry
|
|
5
|
+
* `oauth.scope`; `mcpCredentialScope()` reads both.
|
|
6
6
|
*/
|
|
7
7
|
export type McpOAuthAccountScope = "user" | "org";
|
|
8
8
|
/**
|
|
9
|
-
* **
|
|
10
|
-
*
|
|
9
|
+
* **How this connector gets its credential:** one shared organisation credential, or everyone
|
|
10
|
+
* brings their own.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* The second of the three scope questions, and the only one belonging on the connector:
|
|
13
13
|
*
|
|
14
|
-
* |
|
|
14
|
+
* | Question | Where |
|
|
15
15
|
* |---|---|
|
|
16
|
-
* |
|
|
17
|
-
* |
|
|
18
|
-
* |
|
|
16
|
+
* | Whose *row* is this? | `ownerUserId` / `ManagedAccount.userId` (absent = shared) |
|
|
17
|
+
* | How does it get a credential? | **`credentialScope`** — here |
|
|
18
|
+
* | Who is the *resource* shared with? | `ownerScope` on contacts, work items, memories |
|
|
19
19
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
20
|
+
* It is a **configuration choice of the organisation**, not a property of the vendor: the same MCP
|
|
21
|
+
* server can run on one service account or on a token per user. So it belongs on the connector
|
|
22
|
+
* row, where configuration lives.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* The consequence that makes it matter: **an unattended run (sync, cron, playbook) has no acting
|
|
25
|
+
* user and can therefore never reach a `"per-user"` credential.** That is checkable and
|
|
26
|
+
* explainable up front, instead of ending as a round that saw zero tools.
|
|
27
27
|
*
|
|
28
|
-
* `personalConnect` is
|
|
29
|
-
*
|
|
30
|
-
* met `"per-user"`.
|
|
28
|
+
* `personalConnect` is explicitly not part of this: that is a *permission* (may a member hang
|
|
29
|
+
* their own token on an admin-defined server), not a scope. Only meaningful with `"per-user"`.
|
|
31
30
|
*/
|
|
32
31
|
export type McpCredentialScope = "shared" | "per-user";
|
|
33
32
|
/**
|
|
34
|
-
*
|
|
33
|
+
* A server's credential scope, falling back to the old fields.
|
|
35
34
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* Existing rows carry `oauth.scope`; new ones carry `credentialScope`. One function, so "who
|
|
36
|
+
* brings the token" is never computed twice.
|
|
38
37
|
*/
|
|
39
38
|
export declare function mcpCredentialScope(server: {
|
|
40
39
|
credentialScope?: McpCredentialScope;
|
|
@@ -44,12 +43,11 @@ export declare function mcpCredentialScope(server: {
|
|
|
44
43
|
};
|
|
45
44
|
}): McpCredentialScope;
|
|
46
45
|
/**
|
|
47
|
-
*
|
|
46
|
+
* The naming convention of an MCP tool, in one place.
|
|
48
47
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* geen enkele lookup nodig.
|
|
48
|
+
* A tool is called `mcp__<connectorId>__<toolname>`. The connector id is arbitrary per
|
|
49
|
+
* organisation, so an app cannot hardcode the name — but once it *has* the id (because the
|
|
50
|
+
* connection stores it explicitly, say) this is a pure string and no lookup is needed at all.
|
|
53
51
|
*/
|
|
54
52
|
export declare function mcpToolPrefix(connectorId: string): string;
|
|
55
53
|
/**
|
|
@@ -75,11 +73,11 @@ export interface McpServerConfig {
|
|
|
75
73
|
organizationId: string;
|
|
76
74
|
name: string;
|
|
77
75
|
/**
|
|
78
|
-
*
|
|
76
|
+
* The catalog key this connection came from, as a hint for pickers.
|
|
79
77
|
*
|
|
80
|
-
*
|
|
81
|
-
* Asana"
|
|
82
|
-
*
|
|
78
|
+
* It was on the write body but not on the read view, which is why the "which connection is
|
|
79
|
+
* Asana" answer had to be invented server-side: a client could not see it. Now it can, and
|
|
80
|
+
* pre-filtering is just a `filter` in the UI.
|
|
83
81
|
*/
|
|
84
82
|
catalogKey?: string;
|
|
85
83
|
/** Only Streamable HTTP transport is supported for server-side connections. */
|
|
@@ -93,21 +91,21 @@ export interface McpServerConfig {
|
|
|
93
91
|
/** OAuth settings, present when `authMode === "oauth"`. */
|
|
94
92
|
oauth?: McpOAuthClientView;
|
|
95
93
|
/**
|
|
96
|
-
*
|
|
97
|
-
* {@link mcpCredentialScope},
|
|
94
|
+
* How this connector gets its credential. Absent on old rows — always read it through
|
|
95
|
+
* {@link mcpCredentialScope}, never directly.
|
|
98
96
|
*/
|
|
99
97
|
credentialScope?: McpCredentialScope;
|
|
100
98
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
99
|
+
* Whose ROW this is: absent = defined by the organisation (an admin), set = that user's own
|
|
100
|
+
* custom server. Decides who may change it and where it is visible — separate from
|
|
101
|
+
* {@link McpCredentialScope}, which is about the credential.
|
|
104
102
|
*/
|
|
105
103
|
ownerUserId?: string;
|
|
106
104
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* `credentialScope === "per-user"`.
|
|
110
|
-
*
|
|
105
|
+
* A PERMISSION, not a scope: may a member hang their own credential on this
|
|
106
|
+
* organisation-defined server (the "catalog")? Only meaningful with
|
|
107
|
+
* `credentialScope === "per-user"`. Deliberately not derived — that would silently widen the
|
|
108
|
+
* right for servers where the admin did not allow it.
|
|
111
109
|
*/
|
|
112
110
|
personalConnect?: boolean;
|
|
113
111
|
}
|
|
@@ -140,33 +138,32 @@ export interface McpCatalogEntry {
|
|
|
140
138
|
scope?: McpOAuthAccountScope;
|
|
141
139
|
scopes?: string[];
|
|
142
140
|
};
|
|
143
|
-
/**
|
|
141
|
+
/** The suggested default when adding. Absent = derive from `oauth.scope`. */
|
|
144
142
|
credentialScope?: McpCredentialScope;
|
|
145
143
|
}
|
|
146
144
|
/**
|
|
147
|
-
*
|
|
145
|
+
* What an app may know about a **chosen** connector.
|
|
148
146
|
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
147
|
+
* A preflight, not a search: you arrive with an id someone recorded while configuring, and the
|
|
148
|
+
* question is only "can I still use it". A lookup on primary key, so deterministic by
|
|
149
|
+
* construction — unlike the earlier search by catalog key, which picked an arbitrary winner
|
|
150
|
+
* whenever there were two candidates.
|
|
153
151
|
*/
|
|
154
152
|
export interface McpConnectorDescribe {
|
|
155
153
|
id: string;
|
|
156
154
|
name: string;
|
|
157
|
-
/**
|
|
155
|
+
/** Only when it came from the catalog. */
|
|
158
156
|
catalogKey?: string;
|
|
159
157
|
enabled: boolean;
|
|
160
158
|
credentialScope: McpCredentialScope;
|
|
161
159
|
/**
|
|
162
|
-
*
|
|
160
|
+
* A shared organisation credential exists.
|
|
163
161
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* tien mensen persoonlijk verbonden zijn.
|
|
162
|
+
* The only form an unattended run can use: it has no acting user and so cannot reach a personal
|
|
163
|
+
* token. `false` on a `"per-user"` connector, even when ten people are personally connected.
|
|
167
164
|
*/
|
|
168
165
|
sharedCredential: boolean;
|
|
169
|
-
/** `mcp__<id>__`,
|
|
166
|
+
/** `mcp__<id>__`, same as {@link mcpToolPrefix} — passed along so the caller computes nothing. */
|
|
170
167
|
toolPrefix: string;
|
|
171
168
|
}
|
|
172
169
|
/** Body accepted by the create/update endpoints (write shape, distinct from the read view). */
|
|
@@ -174,13 +171,12 @@ export interface McpServerInput {
|
|
|
174
171
|
name?: string;
|
|
175
172
|
url?: string;
|
|
176
173
|
/**
|
|
177
|
-
*
|
|
174
|
+
* The catalog key this came from ({@link McpCatalogEntry.key}).
|
|
178
175
|
*
|
|
179
|
-
* **
|
|
180
|
-
*
|
|
181
|
-
* connector
|
|
182
|
-
*
|
|
183
|
-
* kiezen en heeft dat eerder ook niet gedaan.
|
|
176
|
+
* **A hint, not a resolution.** It filters the connector picker ("which of your connections is
|
|
177
|
+
* Asana") and feeds the "already added" status in the catalog. Anything needing a connector
|
|
178
|
+
* stores the connector **id** explicitly and uses {@link mcpToolPrefix} — a search by key cannot
|
|
179
|
+
* pick a winner with two candidates, and never could.
|
|
184
180
|
*/
|
|
185
181
|
catalogKey?: string;
|
|
186
182
|
enabled?: boolean;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { MemorySubjectKey } from './item';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Two subjects that turn out to be the same (a merge of interactions, later a real identity
|
|
4
|
+
* layer). The memory does not move: the alias is resolved at read time.
|
|
5
5
|
*
|
|
6
|
-
* **
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* **One level deep by construction**: an alias whose `canonical` is itself an alias is refused at
|
|
7
|
+
* write time. Resolution is therefore two queries and never recursive — no cycle detection, no
|
|
8
|
+
* depth limit, no surprise on the hot path.
|
|
9
9
|
*/
|
|
10
10
|
export interface MemorySubjectAlias {
|
|
11
11
|
id: string;
|
|
12
12
|
organizationId: string;
|
|
13
|
-
/**
|
|
13
|
+
/** The subject that was absorbed into `canonical`. Unique per org. */
|
|
14
14
|
subject: MemorySubjectKey;
|
|
15
15
|
canonical: MemorySubjectKey;
|
|
16
|
-
/**
|
|
16
|
+
/** The app that reported the merge. */
|
|
17
17
|
source: string;
|
|
18
18
|
createdAt?: number;
|
|
19
19
|
}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
import { MemoryItem, MemoryKindId, MemoryVisibility } from './item';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* The admin contract: **everything** in this organisation's memory, flat.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* "
|
|
8
|
-
*
|
|
5
|
+
* Deliberately not a second `MemoryQuery`. That contract is the retrieval engine — ranking,
|
|
6
|
+
* embeddings, character budget, authorization per subject — and answers "what is relevant here".
|
|
7
|
+
* This one asks "what is there". One route would do both worse: the engine must be allowed to
|
|
8
|
+
* filter out what does not score, and an admin page must keep nothing quiet.
|
|
9
9
|
*/
|
|
10
10
|
export interface MemoryBrowseQuery {
|
|
11
|
-
/**
|
|
11
|
+
/** Exact kind. Empty = all of them. */
|
|
12
12
|
kind?: MemoryKindId;
|
|
13
|
-
/**
|
|
13
|
+
/** Writing app (`ai`, `comms`, `context`, …). */
|
|
14
14
|
source?: string;
|
|
15
|
-
/**
|
|
15
|
+
/** The part before the subject's `:` — `interaction`, `contact`, `company`. */
|
|
16
16
|
subjectKind?: string;
|
|
17
|
-
/** Exact subject,
|
|
17
|
+
/** Exact subject, e.g. `contact:c_9`. Beats {@link subjectKind}. */
|
|
18
18
|
subject?: string;
|
|
19
19
|
visibility?: MemoryVisibility;
|
|
20
|
-
/**
|
|
20
|
+
/** Only items with `occurredAt >= since` (ms). */
|
|
21
21
|
since?: number;
|
|
22
|
-
/** Scan
|
|
22
|
+
/** Scan cap. Clamped to {@link MAX_MEMORY_BROWSE}. */
|
|
23
23
|
limit?: number;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Hard upper bound on one admin scan.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
* cap
|
|
30
|
-
*
|
|
31
|
-
*
|
|
28
|
+
* There is no full-text operator in this datastore, so free search happens after fetching. Without
|
|
29
|
+
* a cap an organisation with tens of thousands of items would squeeze its whole memory through one
|
|
30
|
+
* response. When the cap is hit, {@link MemoryBrowseResult.truncated} says so — silently
|
|
31
|
+
* truncating on a page promising "everything" is the one mistake not allowed here.
|
|
32
32
|
*/
|
|
33
33
|
export declare const MAX_MEMORY_BROWSE = 1000;
|
|
34
34
|
export interface MemoryBrowseFacets {
|
|
35
|
-
/**
|
|
35
|
+
/** Sources occurring in this scan, with their count. Descending. */
|
|
36
36
|
sources: Array<{
|
|
37
37
|
value: string;
|
|
38
38
|
count: number;
|
|
@@ -48,13 +48,13 @@ export interface MemoryBrowseFacets {
|
|
|
48
48
|
}
|
|
49
49
|
export interface MemoryBrowseResult {
|
|
50
50
|
items: MemoryItem[];
|
|
51
|
-
/**
|
|
51
|
+
/** How many rows the structural filter yielded (== `items.length`, or the cap). */
|
|
52
52
|
scanned: number;
|
|
53
|
-
/** Cap
|
|
53
|
+
/** Cap hit: there is more than this. Narrow the filter. */
|
|
54
54
|
truncated?: boolean;
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
56
|
+
* What there is to choose in this scan. Derived from the scan and not from a `DISTINCT`, which
|
|
57
|
+
* does not exist here — so on `truncated` these are the facets of the visible part.
|
|
58
58
|
*/
|
|
59
59
|
facets: MemoryBrowseFacets;
|
|
60
60
|
}
|