@xpert-ai/plugin-sdk 3.17.5 → 3.18.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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @xpert-ai/plugin-sdk
2
2
 
3
+ ## 3.18.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8e63a8b: Release Xpert 3.18.0.
8
+
9
+ ### Patch Changes
10
+
11
+ - 477b711: Allow connector plugins to declare an embedded QR authorization presentation while the host manages polling and cancellation.
12
+ - dad112d: Add authoritative Project View runtime scopes, membership and scheduling contracts, read/edit/manage action access, immutable Xpert workspace data scopes, scoped Connector bindings with personal or shared authorization, eligible expert providers, Project-scoped workspace files, and collaboration support.
13
+ - 1c71b75: Add Project-scoped Connector authorization and scheduled tasks that run as a confirmed Project member.
14
+ - d45a0c8: Add governed Project instructions and skills with sandbox read-only enforcement.
15
+ - Updated dependencies [dad112d]
16
+ - Updated dependencies [8e63a8b]
17
+ - Updated dependencies [1c71b75]
18
+ - Updated dependencies [d45a0c8]
19
+ - @xpert-ai/contracts@3.18.0
20
+
21
+ ## 3.17.6
22
+
23
+ ### Patch Changes
24
+
25
+ - afb69b7: Release Xpert 3.17.6 after publishing the complete Sandbox Runtime image suite.
26
+ - Updated dependencies [afb69b7]
27
+ - @xpert-ai/contracts@3.17.6
28
+
3
29
  ## 3.17.5
4
30
 
5
31
  ### Patch Changes
package/connector.cjs.js CHANGED
@@ -1,5 +1,13 @@
1
1
  'use strict';
2
2
 
3
+ const CONNECTOR_SCOPE_TYPES = [
4
+ 'workspace',
5
+ 'project'
6
+ ];
7
+ const CONNECTOR_AUTHORIZATION_MODES = [
8
+ 'personal',
9
+ 'shared'
10
+ ];
3
11
  function getConnectorAuthMethods(definition) {
4
12
  var _definition_legacyAuthMethodId;
5
13
  if ('authMethods' in definition) {
@@ -17,6 +25,14 @@ function getConnectorAuthMethods(definition) {
17
25
  }
18
26
  ];
19
27
  }
28
+ function getConnectorAuthorizationModes(definition) {
29
+ var _definition_authorizationModes;
30
+ return ((_definition_authorizationModes = definition.authorizationModes) == null ? void 0 : _definition_authorizationModes.length) ? [
31
+ ...definition.authorizationModes
32
+ ] : [
33
+ 'shared'
34
+ ];
35
+ }
20
36
  function assertConnectorDefinition(definition) {
21
37
  if (!isObjectValue(definition)) {
22
38
  throw new Error('Connector strategy must expose a valid connector definition');
@@ -32,8 +48,24 @@ function assertConnectorDefinition(definition) {
32
48
  }
33
49
  const auth = Reflect.get(definition, 'auth');
34
50
  const authMethods = Reflect.get(definition, 'authMethods');
51
+ const authorizationModes = Reflect.get(definition, 'authorizationModes');
35
52
  const resolvedMethods = [];
36
53
  const ids = new Set();
54
+ if (authorizationModes !== undefined) {
55
+ if (!Array.isArray(authorizationModes) || !authorizationModes.length) {
56
+ throw new Error(`Connector '${provider}' must declare at least one authorization mode`);
57
+ }
58
+ const seenModes = new Set();
59
+ for (const mode of authorizationModes){
60
+ if (mode !== 'personal' && mode !== 'shared') {
61
+ throw new Error(`Connector '${provider}' has unsupported authorization mode '${String(mode)}'`);
62
+ }
63
+ if (seenModes.has(mode)) {
64
+ throw new Error(`Connector '${provider}' has duplicate authorization mode '${mode}'`);
65
+ }
66
+ seenModes.add(mode);
67
+ }
68
+ }
37
69
  if (authMethods !== undefined) {
38
70
  if (!Array.isArray(authMethods) || !authMethods.length) {
39
71
  throw new Error(`Connector '${provider}' must declare at least one authentication method`);
@@ -98,6 +130,31 @@ function assertConnectorAuthMethod(method, provider) {
98
130
  if (type === 'api_key' && !isObjectValue(Reflect.get(method, 'credentials'))) {
99
131
  throw new Error(`Connector '${provider}' API key method '${idValue.trim()}' must declare credentials`);
100
132
  }
133
+ const authorizationPresentation = Reflect.get(method, 'authorizationPresentation');
134
+ if (authorizationPresentation !== undefined) {
135
+ assertConnectorAuthorizationPresentation(authorizationPresentation, provider, idValue.trim(), type);
136
+ }
137
+ }
138
+ function assertConnectorAuthorizationPresentation(value, provider, authMethodId, authMethodType) {
139
+ if (!isObjectValue(value) || Reflect.get(value, 'mode') !== 'embedded_qr') {
140
+ throw new Error(`Connector '${provider}' authentication method '${authMethodId}' has an invalid authorization presentation`);
141
+ }
142
+ if (authMethodType !== 'oauth2') {
143
+ throw new Error(`Connector '${provider}' authentication method '${authMethodId}' can declare authorization presentation only for OAuth`);
144
+ }
145
+ for (const field of [
146
+ 'title',
147
+ 'description',
148
+ 'ariaLabel',
149
+ 'completionHint',
150
+ 'cancelLabel',
151
+ 'copyLinkLabel',
152
+ 'copyLinkError'
153
+ ]){
154
+ if (!isRuntimeI18nText(Reflect.get(value, field))) {
155
+ throw new Error(`Connector '${provider}' authentication method '${authMethodId}' authorization presentation must declare '${field}'`);
156
+ }
157
+ }
101
158
  }
102
159
  function isConnectorOAuthConfig(value) {
103
160
  return isObjectValue(value) && Reflect.get(value, 'type') === 'oauth2';
@@ -112,5 +169,8 @@ function isObjectValue(value) {
112
169
  return typeof value === 'object' && value !== null;
113
170
  }
114
171
 
172
+ exports.CONNECTOR_AUTHORIZATION_MODES = CONNECTOR_AUTHORIZATION_MODES;
173
+ exports.CONNECTOR_SCOPE_TYPES = CONNECTOR_SCOPE_TYPES;
115
174
  exports.assertConnectorDefinition = assertConnectorDefinition;
116
175
  exports.getConnectorAuthMethods = getConnectorAuthMethods;
176
+ exports.getConnectorAuthorizationModes = getConnectorAuthorizationModes;
package/connector.esm.js CHANGED
@@ -1,3 +1,11 @@
1
+ const CONNECTOR_SCOPE_TYPES = [
2
+ 'workspace',
3
+ 'project'
4
+ ];
5
+ const CONNECTOR_AUTHORIZATION_MODES = [
6
+ 'personal',
7
+ 'shared'
8
+ ];
1
9
  function getConnectorAuthMethods(definition) {
2
10
  var _definition_legacyAuthMethodId;
3
11
  if ('authMethods' in definition) {
@@ -15,6 +23,14 @@ function getConnectorAuthMethods(definition) {
15
23
  }
16
24
  ];
17
25
  }
26
+ function getConnectorAuthorizationModes(definition) {
27
+ var _definition_authorizationModes;
28
+ return ((_definition_authorizationModes = definition.authorizationModes) == null ? void 0 : _definition_authorizationModes.length) ? [
29
+ ...definition.authorizationModes
30
+ ] : [
31
+ 'shared'
32
+ ];
33
+ }
18
34
  function assertConnectorDefinition(definition) {
19
35
  if (!isObjectValue(definition)) {
20
36
  throw new Error('Connector strategy must expose a valid connector definition');
@@ -30,8 +46,24 @@ function assertConnectorDefinition(definition) {
30
46
  }
31
47
  const auth = Reflect.get(definition, 'auth');
32
48
  const authMethods = Reflect.get(definition, 'authMethods');
49
+ const authorizationModes = Reflect.get(definition, 'authorizationModes');
33
50
  const resolvedMethods = [];
34
51
  const ids = new Set();
52
+ if (authorizationModes !== undefined) {
53
+ if (!Array.isArray(authorizationModes) || !authorizationModes.length) {
54
+ throw new Error(`Connector '${provider}' must declare at least one authorization mode`);
55
+ }
56
+ const seenModes = new Set();
57
+ for (const mode of authorizationModes){
58
+ if (mode !== 'personal' && mode !== 'shared') {
59
+ throw new Error(`Connector '${provider}' has unsupported authorization mode '${String(mode)}'`);
60
+ }
61
+ if (seenModes.has(mode)) {
62
+ throw new Error(`Connector '${provider}' has duplicate authorization mode '${mode}'`);
63
+ }
64
+ seenModes.add(mode);
65
+ }
66
+ }
35
67
  if (authMethods !== undefined) {
36
68
  if (!Array.isArray(authMethods) || !authMethods.length) {
37
69
  throw new Error(`Connector '${provider}' must declare at least one authentication method`);
@@ -96,6 +128,31 @@ function assertConnectorAuthMethod(method, provider) {
96
128
  if (type === 'api_key' && !isObjectValue(Reflect.get(method, 'credentials'))) {
97
129
  throw new Error(`Connector '${provider}' API key method '${idValue.trim()}' must declare credentials`);
98
130
  }
131
+ const authorizationPresentation = Reflect.get(method, 'authorizationPresentation');
132
+ if (authorizationPresentation !== undefined) {
133
+ assertConnectorAuthorizationPresentation(authorizationPresentation, provider, idValue.trim(), type);
134
+ }
135
+ }
136
+ function assertConnectorAuthorizationPresentation(value, provider, authMethodId, authMethodType) {
137
+ if (!isObjectValue(value) || Reflect.get(value, 'mode') !== 'embedded_qr') {
138
+ throw new Error(`Connector '${provider}' authentication method '${authMethodId}' has an invalid authorization presentation`);
139
+ }
140
+ if (authMethodType !== 'oauth2') {
141
+ throw new Error(`Connector '${provider}' authentication method '${authMethodId}' can declare authorization presentation only for OAuth`);
142
+ }
143
+ for (const field of [
144
+ 'title',
145
+ 'description',
146
+ 'ariaLabel',
147
+ 'completionHint',
148
+ 'cancelLabel',
149
+ 'copyLinkLabel',
150
+ 'copyLinkError'
151
+ ]){
152
+ if (!isRuntimeI18nText(Reflect.get(value, field))) {
153
+ throw new Error(`Connector '${provider}' authentication method '${authMethodId}' authorization presentation must declare '${field}'`);
154
+ }
155
+ }
99
156
  }
100
157
  function isConnectorOAuthConfig(value) {
101
158
  return isObjectValue(value) && Reflect.get(value, 'type') === 'oauth2';
@@ -110,4 +167,4 @@ function isObjectValue(value) {
110
167
  return typeof value === 'object' && value !== null;
111
168
  }
112
169
 
113
- export { assertConnectorDefinition, getConnectorAuthMethods };
170
+ export { CONNECTOR_AUTHORIZATION_MODES, CONNECTOR_SCOPE_TYPES, assertConnectorDefinition, getConnectorAuthMethods, getConnectorAuthorizationModes };
package/index.cjs.js CHANGED
@@ -32,7 +32,7 @@ var documents = require('@langchain/core/documents');
32
32
  var chat_models = require('@langchain/core/language_models/chat_models');
33
33
  var env = require('@langchain/core/utils/env');
34
34
  var modelProviderHttpClient = require('./model-provider-http-client.cjs.js');
35
- require('js-tiktoken');
35
+ var jsTiktoken = require('js-tiktoken');
36
36
  var base$1 = require('@langchain/core/language_models/base');
37
37
  var connector = require('./connector.cjs.js');
38
38
  var collaborationClient = require('./collaboration-client.cjs.js');
@@ -3144,8 +3144,8 @@ function estimateFallbackUsage(prompts, completion) {
3144
3144
  totalTokens: 0
3145
3145
  };
3146
3146
  }
3147
- const promptTokens = estimateTokens(prompts.join('\n'));
3148
- const completionTokens = estimateTokens(completion != null ? completion : '');
3147
+ const promptTokens = estimateTokens$1(prompts.join('\n'));
3148
+ const completionTokens = estimateTokens$1(completion != null ? completion : '');
3149
3149
  return {
3150
3150
  promptTokens,
3151
3151
  completionTokens,
@@ -3156,7 +3156,7 @@ function readCompletionText(output) {
3156
3156
  var _output_generations;
3157
3157
  return (_output_generations = output.generations) == null ? void 0 : _output_generations.flat().map((generation)=>generation.text).filter(Boolean).join('\n');
3158
3158
  }
3159
- function estimateTokens(text) {
3159
+ function estimateTokens$1(text) {
3160
3160
  const estimatedText = text.replace(/data:image\/[a-zA-Z0-9.+-]+;base64,[a-zA-Z0-9+/_=-]+/g, '[image]');
3161
3161
  let cjkCharacters = 0;
3162
3162
  let otherCharacters = 0;
@@ -3580,12 +3580,60 @@ class Speech2TextChatModel extends chat_models.BaseChatModel {
3580
3580
  }
3581
3581
  }
3582
3582
 
3583
+ const encodingCache = new Map();
3584
+ /**
3585
+ * Fallback token estimation method.
3586
+ *
3587
+ * 思路:
3588
+ * - 英文:约 4 chars / token
3589
+ * - 中文:约 1.5 chars / token
3590
+ * - Mixed:按字符区分
3591
+ */ function estimateTokens(text) {
3592
+ if (!text) return 0;
3593
+ let cn = 0;
3594
+ let en = 0;
3595
+ for (const ch of text){
3596
+ if (/[\u4e00-\u9fa5]/.test(ch)) {
3597
+ cn++;
3598
+ } else {
3599
+ en++;
3600
+ }
3601
+ }
3602
+ // 中文 1 token ≈ 1.5 chars
3603
+ const cnTokens = cn / 1.5;
3604
+ // 英文 1 token ≈ 4 chars
3605
+ const enTokens = en / 4;
3606
+ return Math.ceil(cnTokens + enTokens);
3607
+ }
3583
3608
  /**
3584
3609
  * Count tokens in text
3585
3610
  * 1) Preferred: js-tiktoken precise encoding
3586
3611
  * 2) Fallback: estimated token count
3587
3612
  */ function countTokensSafe(text, opts) {
3588
- return 0;
3613
+ if (!text) return 0;
3614
+ try {
3615
+ let resolvedEncoding;
3616
+ if (opts == null ? void 0 : opts.encodingName) {
3617
+ resolvedEncoding = String(opts.encodingName);
3618
+ } else if (opts == null ? void 0 : opts.model) {
3619
+ var _getEncodingNameForModel;
3620
+ resolvedEncoding = (_getEncodingNameForModel = jsTiktoken.getEncodingNameForModel(opts.model)) != null ? _getEncodingNameForModel : 'cl100k_base';
3621
+ } else {
3622
+ resolvedEncoding = 'cl100k_base';
3623
+ }
3624
+ // Prefer exact token count via js-tiktoken
3625
+ const cacheKey = (opts == null ? void 0 : opts.model) ? `model:${opts.model}` : `encoding:${resolvedEncoding}`;
3626
+ let enc = encodingCache.get(cacheKey);
3627
+ if (!enc) {
3628
+ enc = (opts == null ? void 0 : opts.model) ? jsTiktoken.encodingForModel(opts.model) : jsTiktoken.getEncoding(resolvedEncoding);
3629
+ encodingCache.set(cacheKey, enc);
3630
+ }
3631
+ const tokens = enc.encode(text);
3632
+ return tokens.length;
3633
+ } catch (e) {
3634
+ // Provider-specific model names are not always known by js-tiktoken.
3635
+ return estimateTokens(text);
3636
+ }
3589
3637
  }
3590
3638
 
3591
3639
  function getModelContextSize(input) {
@@ -5833,8 +5881,11 @@ exports.createRuntimeCapability = modelProvider.createRuntimeCapability;
5833
5881
  exports.isSandboxJobRuntimeError = modelProvider.isSandboxJobRuntimeError;
5834
5882
  exports.ModelProviderHttpClient = modelProviderHttpClient.ModelProviderHttpClient;
5835
5883
  exports.ModelProviderHttpError = modelProviderHttpClient.ModelProviderHttpError;
5884
+ exports.CONNECTOR_AUTHORIZATION_MODES = connector.CONNECTOR_AUTHORIZATION_MODES;
5885
+ exports.CONNECTOR_SCOPE_TYPES = connector.CONNECTOR_SCOPE_TYPES;
5836
5886
  exports.assertConnectorDefinition = connector.assertConnectorDefinition;
5837
5887
  exports.getConnectorAuthMethods = connector.getConnectorAuthMethods;
5888
+ exports.getConnectorAuthorizationModes = connector.getConnectorAuthorizationModes;
5838
5889
  exports.base64ToBytes = collaborationClient.base64ToBytes;
5839
5890
  exports.bytesToBase64 = collaborationClient.bytesToBase64;
5840
5891
  exports.createCollaborationClient = collaborationClient.createCollaborationClient;
package/index.esm.js CHANGED
@@ -35,10 +35,10 @@ import { Document } from '@langchain/core/documents';
35
35
  import { BaseChatModel } from '@langchain/core/language_models/chat_models';
36
36
  import { getEnvironmentVariable } from '@langchain/core/utils/env';
37
37
  export { ModelProviderHttpClient, ModelProviderHttpError } from './model-provider-http-client.esm.js';
38
- import 'js-tiktoken';
38
+ import { getEncodingNameForModel, encodingForModel, getEncoding } from 'js-tiktoken';
39
39
  import { getModelContextSize as getModelContextSize$1 } from '@langchain/core/language_models/base';
40
40
  import { assertConnectorDefinition } from './connector.esm.js';
41
- export { getConnectorAuthMethods } from './connector.esm.js';
41
+ export { CONNECTOR_AUTHORIZATION_MODES, CONNECTOR_SCOPE_TYPES, getConnectorAuthMethods, getConnectorAuthorizationModes } from './connector.esm.js';
42
42
  export { base64ToBytes, bytesToBase64, createCollaborationClient, createCollaborationPresenceStore, createSocketIoTransportAdapter, createYjsDocumentAdapter } from './collaboration-client.esm.js';
43
43
  import '@langchain/core/tools';
44
44
  import 'zod/v3';
@@ -3126,8 +3126,8 @@ function estimateFallbackUsage(prompts, completion) {
3126
3126
  totalTokens: 0
3127
3127
  };
3128
3128
  }
3129
- const promptTokens = estimateTokens(prompts.join('\n'));
3130
- const completionTokens = estimateTokens(completion != null ? completion : '');
3129
+ const promptTokens = estimateTokens$1(prompts.join('\n'));
3130
+ const completionTokens = estimateTokens$1(completion != null ? completion : '');
3131
3131
  return {
3132
3132
  promptTokens,
3133
3133
  completionTokens,
@@ -3138,7 +3138,7 @@ function readCompletionText(output) {
3138
3138
  var _output_generations;
3139
3139
  return (_output_generations = output.generations) == null ? void 0 : _output_generations.flat().map((generation)=>generation.text).filter(Boolean).join('\n');
3140
3140
  }
3141
- function estimateTokens(text) {
3141
+ function estimateTokens$1(text) {
3142
3142
  const estimatedText = text.replace(/data:image\/[a-zA-Z0-9.+-]+;base64,[a-zA-Z0-9+/_=-]+/g, '[image]');
3143
3143
  let cjkCharacters = 0;
3144
3144
  let otherCharacters = 0;
@@ -3562,12 +3562,60 @@ class Speech2TextChatModel extends BaseChatModel {
3562
3562
  }
3563
3563
  }
3564
3564
 
3565
+ const encodingCache = new Map();
3566
+ /**
3567
+ * Fallback token estimation method.
3568
+ *
3569
+ * 思路:
3570
+ * - 英文:约 4 chars / token
3571
+ * - 中文:约 1.5 chars / token
3572
+ * - Mixed:按字符区分
3573
+ */ function estimateTokens(text) {
3574
+ if (!text) return 0;
3575
+ let cn = 0;
3576
+ let en = 0;
3577
+ for (const ch of text){
3578
+ if (/[\u4e00-\u9fa5]/.test(ch)) {
3579
+ cn++;
3580
+ } else {
3581
+ en++;
3582
+ }
3583
+ }
3584
+ // 中文 1 token ≈ 1.5 chars
3585
+ const cnTokens = cn / 1.5;
3586
+ // 英文 1 token ≈ 4 chars
3587
+ const enTokens = en / 4;
3588
+ return Math.ceil(cnTokens + enTokens);
3589
+ }
3565
3590
  /**
3566
3591
  * Count tokens in text
3567
3592
  * 1) Preferred: js-tiktoken precise encoding
3568
3593
  * 2) Fallback: estimated token count
3569
3594
  */ function countTokensSafe(text, opts) {
3570
- return 0;
3595
+ if (!text) return 0;
3596
+ try {
3597
+ let resolvedEncoding;
3598
+ if (opts == null ? void 0 : opts.encodingName) {
3599
+ resolvedEncoding = String(opts.encodingName);
3600
+ } else if (opts == null ? void 0 : opts.model) {
3601
+ var _getEncodingNameForModel;
3602
+ resolvedEncoding = (_getEncodingNameForModel = getEncodingNameForModel(opts.model)) != null ? _getEncodingNameForModel : 'cl100k_base';
3603
+ } else {
3604
+ resolvedEncoding = 'cl100k_base';
3605
+ }
3606
+ // Prefer exact token count via js-tiktoken
3607
+ const cacheKey = (opts == null ? void 0 : opts.model) ? `model:${opts.model}` : `encoding:${resolvedEncoding}`;
3608
+ let enc = encodingCache.get(cacheKey);
3609
+ if (!enc) {
3610
+ enc = (opts == null ? void 0 : opts.model) ? encodingForModel(opts.model) : getEncoding(resolvedEncoding);
3611
+ encodingCache.set(cacheKey, enc);
3612
+ }
3613
+ const tokens = enc.encode(text);
3614
+ return tokens.length;
3615
+ } catch (e) {
3616
+ // Provider-specific model names are not always known by js-tiktoken.
3617
+ return estimateTokens(text);
3618
+ }
3571
3619
  }
3572
3620
 
3573
3621
  function getModelContextSize(input) {
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var modelProvider = require('./model-provider.cjs.js');
4
- require('@xpert-ai/contracts');
5
4
  require('./_extends.cjs.js');
5
+ require('@xpert-ai/contracts');
6
6
  require('@nestjs/common');
7
7
  require('@langchain/core/tools');
8
8
  require('zod/v3');
@@ -1,6 +1,6 @@
1
1
  export { M as ModelProviderBuiltinToolset } from './model-provider.esm.js';
2
- import '@xpert-ai/contracts';
3
2
  import './_extends.esm.js';
3
+ import '@xpert-ai/contracts';
4
4
  import '@nestjs/common';
5
5
  import '@langchain/core/tools';
6
6
  import 'zod/v3';
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var contracts = require('@xpert-ai/contracts');
4
3
  var _extends = require('./_extends.cjs.js');
4
+ var contracts = require('@xpert-ai/contracts');
5
5
  var common = require('@nestjs/common');
6
6
  var tools = require('@langchain/core/tools');
7
7
  var v3 = require('zod/v3');
@@ -189,7 +189,7 @@ const KnowledgebaseProvisioningRuntimeCapability = createRuntimeCapability('plat
189
189
  });
190
190
 
191
191
  const KnowledgebaseDocumentsRuntimeCapability = createRuntimeCapability('platform.knowledgebase.documents', {
192
- description: 'Upload, import, create, process, inspect, and delete persistent knowledgebase documents.'
192
+ description: 'Upload, import, create, process, reprocess, inspect, and delete persistent knowledgebase documents.'
193
193
  });
194
194
 
195
195
  const KnowledgeDocumentVisualAssetsRuntimeCapability = createRuntimeCapability('platform.knowledgebase.visual-assets', {
@@ -277,36 +277,23 @@ const ProjectProvisioningRuntimeCapability = createRuntimeCapability('platform.p
277
277
  return match[1];
278
278
  }
279
279
  getWorkspaceFiles() {
280
- var _this_runtimeCapabilities;
281
- const workspaceFiles = (_this_runtimeCapabilities = this.runtimeCapabilities) == null ? void 0 : _this_runtimeCapabilities.get(WorkspaceFilesRuntimeCapability);
280
+ var _this_params_runtimeCapabilities, _this_params;
281
+ const workspaceFiles = (_this_params = this.params) == null ? void 0 : (_this_params_runtimeCapabilities = _this_params.runtimeCapabilities) == null ? void 0 : _this_params_runtimeCapabilities.get(WorkspaceFilesRuntimeCapability);
282
282
  if (!workspaceFiles) {
283
283
  throw new Error(this.modelProviderOptions.missingWorkspaceMessage);
284
284
  }
285
285
  return workspaceFiles;
286
286
  }
287
287
  createWorkspaceScope() {
288
- var _this_params, _this_params1, _this_params2;
289
- const projectId = normalizeOptionalString((_this_params = this.params) == null ? void 0 : _this_params.projectId);
290
- if (projectId) {
291
- var _this_params3, _this_params4;
292
- return {
293
- tenantId: normalizeOptionalString((_this_params3 = this.params) == null ? void 0 : _this_params3.tenantId),
294
- userId: normalizeOptionalString((_this_params4 = this.params) == null ? void 0 : _this_params4.userId),
295
- catalog: 'projects',
296
- scopeId: projectId,
297
- projectId
298
- };
288
+ var _this_params, _this_params1;
289
+ const runtimeScope = (_this_params = this.params) == null ? void 0 : _this_params.runtimeScope;
290
+ if (runtimeScope) {
291
+ return normalizeWorkspaceScope(runtimeScope);
299
292
  }
300
- const xpertId = normalizeOptionalString(this.xpertId);
301
- if (!xpertId) return undefined;
302
- return {
303
- tenantId: normalizeOptionalString((_this_params1 = this.params) == null ? void 0 : _this_params1.tenantId),
304
- userId: normalizeOptionalString((_this_params2 = this.params) == null ? void 0 : _this_params2.userId),
305
- catalog: 'xperts',
306
- scopeId: xpertId,
307
- xpertId,
308
- isolateByUser: false
309
- };
293
+ if (normalizeOptionalString((_this_params1 = this.params) == null ? void 0 : _this_params1.projectId) || normalizeOptionalString(this.xpertId)) {
294
+ throw new Error(this.modelProviderOptions.missingWorkspaceMessage);
295
+ }
296
+ return undefined;
310
297
  }
311
298
  async createAsyncModelClient(model, modality, purpose = 'invoke') {
312
299
  const modelProvider = await this.getModelProviderRuntime();
@@ -336,16 +323,48 @@ const ProjectProvisioningRuntimeCapability = createRuntimeCapability('platform.p
336
323
  modelType
337
324
  }, {});
338
325
  }
339
- constructor(modelProviderOptions, toolset, runtimeCapabilities, params){
326
+ constructor(modelProviderOptions, toolset, _runtimeCapabilities, params){
340
327
  super(modelProviderOptions.toolsetProviderName, toolset, params);
341
328
  this.modelProviderOptions = modelProviderOptions;
342
- this.runtimeCapabilities = runtimeCapabilities;
343
329
  }
344
330
  }
345
331
  function normalizeOptionalString(value) {
346
332
  const normalized = value == null ? void 0 : value.trim();
347
333
  return normalized || undefined;
348
334
  }
335
+ function normalizeWorkspaceScope(scope) {
336
+ const tenantId = normalizeOptionalString(scope.tenantId);
337
+ const organizationId = normalizeOptionalString(scope.organizationId);
338
+ const userId = normalizeOptionalString(scope.userId);
339
+ var _scope_catalog;
340
+ const catalog = (_scope_catalog = scope.catalog) != null ? _scope_catalog : undefined;
341
+ const scopeId = normalizeOptionalString(scope.scopeId);
342
+ const projectId = normalizeOptionalString(scope.projectId);
343
+ const knowledgeId = normalizeOptionalString(scope.knowledgeId);
344
+ const rootId = normalizeOptionalString(scope.rootId);
345
+ const xpertId = normalizeOptionalString(scope.xpertId);
346
+ return _extends._extends({}, tenantId ? {
347
+ tenantId
348
+ } : {}, organizationId ? {
349
+ organizationId
350
+ } : {}, userId ? {
351
+ userId
352
+ } : {}, catalog ? {
353
+ catalog
354
+ } : {}, scopeId ? {
355
+ scopeId
356
+ } : {}, projectId ? {
357
+ projectId
358
+ } : {}, knowledgeId ? {
359
+ knowledgeId
360
+ } : {}, rootId ? {
361
+ rootId
362
+ } : {}, xpertId ? {
363
+ xpertId
364
+ } : {}, typeof scope.isolateByUser === 'boolean' ? {
365
+ isolateByUser: scope.isolateByUser
366
+ } : {});
367
+ }
349
368
 
350
369
  exports.ActorTokenRuntimeCapability = ActorTokenRuntimeCapability;
351
370
  exports.ArtifactsRuntimeCapability = ArtifactsRuntimeCapability;
@@ -1,5 +1,5 @@
1
- import { AiModelTypeEnum } from '@xpert-ai/contracts';
2
1
  import { _ as _extends } from './_extends.esm.js';
2
+ import { AiModelTypeEnum } from '@xpert-ai/contracts';
3
3
  import { Logger } from '@nestjs/common';
4
4
  import { BaseToolkit, StructuredTool } from '@langchain/core/tools';
5
5
  import { z } from 'zod/v3';
@@ -187,7 +187,7 @@ const KnowledgebaseProvisioningRuntimeCapability = createRuntimeCapability('plat
187
187
  });
188
188
 
189
189
  const KnowledgebaseDocumentsRuntimeCapability = createRuntimeCapability('platform.knowledgebase.documents', {
190
- description: 'Upload, import, create, process, inspect, and delete persistent knowledgebase documents.'
190
+ description: 'Upload, import, create, process, reprocess, inspect, and delete persistent knowledgebase documents.'
191
191
  });
192
192
 
193
193
  const KnowledgeDocumentVisualAssetsRuntimeCapability = createRuntimeCapability('platform.knowledgebase.visual-assets', {
@@ -275,36 +275,23 @@ const ProjectProvisioningRuntimeCapability = createRuntimeCapability('platform.p
275
275
  return match[1];
276
276
  }
277
277
  getWorkspaceFiles() {
278
- var _this_runtimeCapabilities;
279
- const workspaceFiles = (_this_runtimeCapabilities = this.runtimeCapabilities) == null ? void 0 : _this_runtimeCapabilities.get(WorkspaceFilesRuntimeCapability);
278
+ var _this_params_runtimeCapabilities, _this_params;
279
+ const workspaceFiles = (_this_params = this.params) == null ? void 0 : (_this_params_runtimeCapabilities = _this_params.runtimeCapabilities) == null ? void 0 : _this_params_runtimeCapabilities.get(WorkspaceFilesRuntimeCapability);
280
280
  if (!workspaceFiles) {
281
281
  throw new Error(this.modelProviderOptions.missingWorkspaceMessage);
282
282
  }
283
283
  return workspaceFiles;
284
284
  }
285
285
  createWorkspaceScope() {
286
- var _this_params, _this_params1, _this_params2;
287
- const projectId = normalizeOptionalString((_this_params = this.params) == null ? void 0 : _this_params.projectId);
288
- if (projectId) {
289
- var _this_params3, _this_params4;
290
- return {
291
- tenantId: normalizeOptionalString((_this_params3 = this.params) == null ? void 0 : _this_params3.tenantId),
292
- userId: normalizeOptionalString((_this_params4 = this.params) == null ? void 0 : _this_params4.userId),
293
- catalog: 'projects',
294
- scopeId: projectId,
295
- projectId
296
- };
286
+ var _this_params, _this_params1;
287
+ const runtimeScope = (_this_params = this.params) == null ? void 0 : _this_params.runtimeScope;
288
+ if (runtimeScope) {
289
+ return normalizeWorkspaceScope(runtimeScope);
297
290
  }
298
- const xpertId = normalizeOptionalString(this.xpertId);
299
- if (!xpertId) return undefined;
300
- return {
301
- tenantId: normalizeOptionalString((_this_params1 = this.params) == null ? void 0 : _this_params1.tenantId),
302
- userId: normalizeOptionalString((_this_params2 = this.params) == null ? void 0 : _this_params2.userId),
303
- catalog: 'xperts',
304
- scopeId: xpertId,
305
- xpertId,
306
- isolateByUser: false
307
- };
291
+ if (normalizeOptionalString((_this_params1 = this.params) == null ? void 0 : _this_params1.projectId) || normalizeOptionalString(this.xpertId)) {
292
+ throw new Error(this.modelProviderOptions.missingWorkspaceMessage);
293
+ }
294
+ return undefined;
308
295
  }
309
296
  async createAsyncModelClient(model, modality, purpose = 'invoke') {
310
297
  const modelProvider = await this.getModelProviderRuntime();
@@ -334,15 +321,47 @@ const ProjectProvisioningRuntimeCapability = createRuntimeCapability('platform.p
334
321
  modelType
335
322
  }, {});
336
323
  }
337
- constructor(modelProviderOptions, toolset, runtimeCapabilities, params){
324
+ constructor(modelProviderOptions, toolset, _runtimeCapabilities, params){
338
325
  super(modelProviderOptions.toolsetProviderName, toolset, params);
339
326
  this.modelProviderOptions = modelProviderOptions;
340
- this.runtimeCapabilities = runtimeCapabilities;
341
327
  }
342
328
  }
343
329
  function normalizeOptionalString(value) {
344
330
  const normalized = value == null ? void 0 : value.trim();
345
331
  return normalized || undefined;
346
332
  }
333
+ function normalizeWorkspaceScope(scope) {
334
+ const tenantId = normalizeOptionalString(scope.tenantId);
335
+ const organizationId = normalizeOptionalString(scope.organizationId);
336
+ const userId = normalizeOptionalString(scope.userId);
337
+ var _scope_catalog;
338
+ const catalog = (_scope_catalog = scope.catalog) != null ? _scope_catalog : undefined;
339
+ const scopeId = normalizeOptionalString(scope.scopeId);
340
+ const projectId = normalizeOptionalString(scope.projectId);
341
+ const knowledgeId = normalizeOptionalString(scope.knowledgeId);
342
+ const rootId = normalizeOptionalString(scope.rootId);
343
+ const xpertId = normalizeOptionalString(scope.xpertId);
344
+ return _extends({}, tenantId ? {
345
+ tenantId
346
+ } : {}, organizationId ? {
347
+ organizationId
348
+ } : {}, userId ? {
349
+ userId
350
+ } : {}, catalog ? {
351
+ catalog
352
+ } : {}, scopeId ? {
353
+ scopeId
354
+ } : {}, projectId ? {
355
+ projectId
356
+ } : {}, knowledgeId ? {
357
+ knowledgeId
358
+ } : {}, rootId ? {
359
+ rootId
360
+ } : {}, xpertId ? {
361
+ xpertId
362
+ } : {}, typeof scope.isolateByUser === 'boolean' ? {
363
+ isolateByUser: scope.isolateByUser
364
+ } : {});
365
+ }
347
366
 
348
367
  export { ActorTokenRuntimeCapability as A, BaseTool as B, DefaultRuntimeCapabilityRegistry as D, KnowledgeDocumentVisualAssetsRuntimeCapability as K, ModelProviderBuiltinToolset as M, ProjectProvisioningRuntimeCapability as P, SANDBOX_JOB_ERROR_CODES as S, WORKSPACE_FILES_SOURCE as W, XPERT_RUNTIME_CAPABILITIES_TOKEN as X, ArtifactsRuntimeCapability as a, BaseToolset as b, createRuntimeCapability as c, BuiltinToolset as d, KnowledgebaseDocumentsRuntimeCapability as e, KnowledgebaseProvisioningRuntimeCapability as f, KnowledgebaseRuntimeCapability as g, SANDBOX_JOB_PROGRESS_PREFIX as h, SandboxJobRuntimeError as i, SandboxJobsRuntimeCapability as j, WorkspaceFilesRuntimeCapability as k, isSandboxJobRuntimeError as l };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xpert-ai/plugin-sdk",
3
- "version": "3.17.5",
3
+ "version": "3.18.0",
4
4
  "license": "AGPL-3.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@langchain/openai": "0.6.9",
20
- "@xpert-ai/contracts": "3.17.5",
20
+ "@xpert-ai/contracts": "3.18.0",
21
21
  "express": "^4.22.1",
22
22
  "js-tiktoken": "^1.0.21"
23
23
  },
@@ -1,4 +1,4 @@
1
- import type { JSONValue } from '@xpert-ai/contracts';
1
+ import type { JSONValue, TAvatar } from '@xpert-ai/contracts';
2
2
  export type AgentMiddlewareAssistantTaskStatus = 'queued' | 'running' | 'succeeded' | 'failed' | 'interrupted' | 'unknown';
3
3
  export type AgentMiddlewareAssistantTaskFile = {
4
4
  id?: string;
@@ -23,9 +23,81 @@ export type AgentMiddlewareAssistantTaskSkillRef = {
23
23
  pluginName: string;
24
24
  componentKey: string;
25
25
  };
26
+ /**
27
+ * Portable role identity used to resolve an organization-owned Assistant.
28
+ * Instance UUIDs stay out of plugin contracts so the same workflow is deployable across organizations.
29
+ */
30
+ export type AgentMiddlewareExternalAssistantExpectation = {
31
+ pluginName: string;
32
+ templateKey: string;
33
+ agentKey: string;
34
+ };
35
+ /** Resolve the executor from the requester's required, direct external-Xpert connections. */
36
+ export type AgentMiddlewareAssistantTaskTarget = {
37
+ kind: 'external_assistant';
38
+ requesterXpertId: string;
39
+ requesterAgentKey: string;
40
+ expectation: AgentMiddlewareExternalAssistantExpectation;
41
+ };
42
+ /** Stable plugin-owned identity for reconciling platform executions with a domain operation. */
43
+ export type AgentMiddlewareExecutionCorrelation = {
44
+ namespace: string;
45
+ operationId: string;
46
+ subjectId: string;
47
+ attributes?: Record<string, JSONValue>;
48
+ };
49
+ /** Availability of a resolved external Assistant binding. */
50
+ export type AgentMiddlewareExternalAssistantBindingStatus = 'available' | 'incompatible' | 'unpublished' | 'cross_organization';
51
+ /** Safe external Assistant metadata that may cross plugin and View Host boundaries. */
52
+ export type AgentMiddlewareExternalAssistantBinding = {
53
+ title: string;
54
+ name: string;
55
+ avatar?: TAvatar;
56
+ templateSource: {
57
+ templateId: string;
58
+ templateKey: string;
59
+ pluginName?: string;
60
+ source?: string;
61
+ } | null;
62
+ primaryAgentKey?: string;
63
+ publishedVersion?: string;
64
+ status: AgentMiddlewareExternalAssistantBindingStatus;
65
+ };
66
+ /** Identifies the requester whose required direct bindings should be listed. */
67
+ export type AgentMiddlewareListExternalAssistantBindingsInput = {
68
+ requesterXpertId: string;
69
+ requesterAgentKey: string;
70
+ };
71
+ /** Selects correlated executions for one requester-owned domain subject. */
72
+ export type AgentMiddlewareListCorrelatedExecutionsInput = {
73
+ requesterXpertId: string;
74
+ requesterAgentKey: string;
75
+ namespace: string;
76
+ subjectId: string;
77
+ limit?: number;
78
+ };
79
+ /** Safe execution summary returned to a plugin for domain reconciliation. */
80
+ export type AgentMiddlewareCorrelatedExecution = {
81
+ operationId: string;
82
+ subjectId: string;
83
+ attributes?: Record<string, JSONValue>;
84
+ status: AgentMiddlewareAssistantTaskStatus;
85
+ executionId: string;
86
+ parentExecutionId?: string;
87
+ threadId?: string;
88
+ executorXpertId: string;
89
+ executorAgentKey?: string;
90
+ executorAssistantTemplateKey?: string;
91
+ executorAssistantTitle?: string;
92
+ executorPublishedVersion?: string;
93
+ startedAt?: string;
94
+ updatedAt?: string;
95
+ };
26
96
  export type AgentMiddlewareAssistantTaskInput = {
27
97
  xpertId: string;
28
98
  agentKey?: string;
99
+ /** Resolve an organization-owned external Assistant from the requester's published graph. */
100
+ target?: AgentMiddlewareAssistantTaskTarget;
29
101
  conversationId?: string | null;
30
102
  executionId?: string | null;
31
103
  projectId?: string | null;
@@ -38,6 +110,7 @@ export type AgentMiddlewareAssistantTaskInput = {
38
110
  /** Additional bounded human-input fields exposed to runtime-state fixed filters. */
39
111
  humanInput?: Record<string, JSONValue>;
40
112
  context?: Record<string, unknown>;
113
+ correlation?: AgentMiddlewareExecutionCorrelation;
41
114
  };
42
115
  export type AgentMiddlewareAssistantTaskResult = {
43
116
  status: AgentMiddlewareAssistantTaskStatus;
@@ -46,6 +119,11 @@ export type AgentMiddlewareAssistantTaskResult = {
46
119
  conversationId?: string;
47
120
  threadId?: string;
48
121
  errorMessage?: string;
122
+ executorXpertId?: string;
123
+ executorAgentKey?: string;
124
+ executorAssistantTemplateKey?: string;
125
+ executorAssistantTitle?: string;
126
+ executorPublishedVersion?: string;
49
127
  };
50
128
  export type AgentMiddlewareAssistantTaskStatusInput = {
51
129
  taskId?: string;
@@ -60,6 +138,10 @@ export type AgentMiddlewareAssistantTaskCancelResult = {
60
138
  };
61
139
  export interface AgentMiddlewareAssistantTaskApi {
62
140
  startTask(input: AgentMiddlewareAssistantTaskInput): Promise<AgentMiddlewareAssistantTaskResult>;
141
+ /** Return only safe binding descriptors; internal Assistant instance IDs are intentionally omitted. */
142
+ listExternalAssistantBindings?(input: AgentMiddlewareListExternalAssistantBindingsInput): Promise<AgentMiddlewareExternalAssistantBinding[]>;
143
+ /** Read executions owned by the requester and its currently bound external Assistants. */
144
+ listCorrelatedExecutions?(input: AgentMiddlewareListCorrelatedExecutionsInput): Promise<AgentMiddlewareCorrelatedExecution[]>;
63
145
  getTaskStatus?(input: AgentMiddlewareAssistantTaskStatusInput): Promise<AgentMiddlewareAssistantTaskResult | null>;
64
146
  cancelTask?(input: AgentMiddlewareAssistantTaskStatusInput): Promise<AgentMiddlewareAssistantTaskCancelResult>;
65
147
  }
@@ -7,6 +7,7 @@ import { ICopilotModel, IModelAccessResolution, IXpertAgentExecution, JSONValue,
7
7
  import { Subscriber } from 'rxjs';
8
8
  import { AIGCModelClient, AsyncAIGCModelClient, IRerank, TLLMUsage } from '../../ai-model/types';
9
9
  import type { RuntimeCapabilityRegistry } from '../../core';
10
+ import type { WorkspaceFileCatalog } from '../../runtime/capabilities/workspace-files';
10
11
  export * from './runtime-capability';
11
12
  export * from './capabilities';
12
13
  /**
@@ -99,10 +100,19 @@ export type AgentMiddlewareRuntimeScope = {
99
100
  workspaceId?: string | null;
100
101
  projectId?: string | null;
101
102
  xpertId?: string | null;
103
+ /** Authoritative Volume catalog for runtime workspace files. */
104
+ catalog?: WorkspaceFileCatalog | null;
105
+ /** Authoritative catalog identity for portable workspace references. */
106
+ scopeId?: string | null;
107
+ /** Legacy xperts catalog compatibility flag; new runtimes use user-xperts instead. */
108
+ isolateByUser?: boolean | null;
102
109
  xpertName?: string | null;
103
110
  conversationId?: string | null;
111
+ threadId?: string | null;
104
112
  agentKey?: string | null;
105
113
  executionId?: string | null;
114
+ /** Connector bindings selected for this conversation. An empty list denies connector resolution. */
115
+ connectorBindingIds?: string[] | null;
106
116
  usageCallback?: (usage: TLLMUsage) => void | Promise<void>;
107
117
  workspaceRoot?: string | null;
108
118
  workspacePath?: string | null;
@@ -1,4 +1,4 @@
1
- import { IWFNMiddleware, TAgentMiddlewareMeta, TXpertFeatures } from '@xpert-ai/contracts';
1
+ import { IWFNMiddleware, TAgentMiddlewareMeta, TXpertFeatures, XpertWorkspaceDataScope } from '@xpert-ai/contracts';
2
2
  import { StructuredToolInterface } from '@langchain/core/tools';
3
3
  import { RunnableToolLike } from '@langchain/core/runnables';
4
4
  import { BaseStore } from '@langchain/langgraph';
@@ -12,7 +12,9 @@ export interface IAgentMiddlewareContext {
12
12
  workspaceId?: string;
13
13
  projectId?: string;
14
14
  conversationId?: string;
15
+ threadId?: string;
15
16
  xpertId?: string;
17
+ workspaceDataScope?: XpertWorkspaceDataScope | null;
16
18
  xpertFeatures?: TXpertFeatures | null;
17
19
  agentKey?: string;
18
20
  knowledgebaseIds?: string[];
@@ -2,6 +2,17 @@ import type { I18nText, IconDefinition } from '@xpert-ai/contracts';
2
2
  export type RuntimeI18nText = I18nText;
3
3
  export type RuntimeCapabilityIcon = IconDefinition;
4
4
  export type ConnectorStatus = 'pending' | 'active' | 'expired' | 'error' | 'disconnected';
5
+ export declare const CONNECTOR_SCOPE_TYPES: readonly ["workspace", "project"];
6
+ export type ConnectorScopeType = (typeof CONNECTOR_SCOPE_TYPES)[number];
7
+ export type ConnectorScope = {
8
+ type: 'workspace';
9
+ workspaceId: string;
10
+ } | {
11
+ type: 'project';
12
+ projectId: string;
13
+ };
14
+ export declare const CONNECTOR_AUTHORIZATION_MODES: readonly ["personal", "shared"];
15
+ export type ConnectorAuthorizationMode = (typeof CONNECTOR_AUTHORIZATION_MODES)[number];
5
16
  export type ConnectorOAuthConfig = {
6
17
  type: 'oauth2';
7
18
  authorizationUrl?: string;
@@ -28,17 +39,28 @@ export type ConnectorAppCredentialsConfig = {
28
39
  defaultValues?: Record<string, string | number | boolean | null>;
29
40
  };
30
41
  export type ConnectorCredentialFormDefinition = ConnectorAppCredentialsConfig;
31
- export type ConnectorAuthMethodDefinition = {
42
+ export type ConnectorAuthorizationPresentation = {
43
+ mode: 'embedded_qr';
44
+ title: RuntimeI18nText;
45
+ description: RuntimeI18nText;
46
+ ariaLabel: RuntimeI18nText;
47
+ completionHint: RuntimeI18nText;
48
+ cancelLabel: RuntimeI18nText;
49
+ copyLinkLabel: RuntimeI18nText;
50
+ copyLinkError: RuntimeI18nText;
51
+ };
52
+ type ConnectorAuthMethodBase = {
32
53
  id: string;
33
- type: 'oauth2';
34
54
  label: RuntimeI18nText;
55
+ authorizationPresentation?: ConnectorAuthorizationPresentation;
56
+ };
57
+ export type ConnectorAuthMethodDefinition = ConnectorAuthMethodBase & ({
58
+ type: 'oauth2';
35
59
  appCredentials?: ConnectorCredentialFormDefinition;
36
60
  } | {
37
- id: string;
38
61
  type: 'api_key';
39
- label: RuntimeI18nText;
40
62
  credentials: ConnectorCredentialFormDefinition;
41
- };
63
+ });
42
64
  export type ConnectorPermissionDeclaration = {
43
65
  key: string;
44
66
  label?: RuntimeI18nText;
@@ -55,6 +77,8 @@ export type ConnectorDefinitionBase = {
55
77
  description?: RuntimeI18nText;
56
78
  icon?: RuntimeCapabilityIcon;
57
79
  permissions?: ConnectorPermissionDeclaration[];
80
+ /** Credential ownership modes supported by this provider. Legacy providers are shared-only. */
81
+ authorizationModes?: ConnectorAuthorizationMode[];
58
82
  /** Maps credentials stored before multi-auth support to a declared OAuth method. */
59
83
  legacyAuthMethodId?: string;
60
84
  };
@@ -70,6 +94,7 @@ export type ConnectorMultiAuthDefinition = ConnectorDefinitionBase & {
70
94
  };
71
95
  export type ConnectorStrategyDefinition = ConnectorDefinition | ConnectorMultiAuthDefinition;
72
96
  export declare function getConnectorAuthMethods(definition: ConnectorStrategyDefinition): ConnectorAuthMethodDefinition[];
97
+ export declare function getConnectorAuthorizationModes(definition: ConnectorStrategyDefinition): ConnectorAuthorizationMode[];
73
98
  export declare function assertConnectorDefinition(definition: unknown): asserts definition is ConnectorStrategyDefinition;
74
99
  export type ConnectorProfile = {
75
100
  openId?: string;
@@ -82,7 +107,12 @@ export type ConnectorProfile = {
82
107
  };
83
108
  export type ConnectorInstance = {
84
109
  id: string;
85
- workspaceId: string;
110
+ /** @deprecated Prefer scope. */
111
+ workspaceId?: string | null;
112
+ projectId?: string | null;
113
+ scopeType?: ConnectorScopeType;
114
+ scope?: ConnectorScope;
115
+ authorizationMode?: ConnectorAuthorizationMode;
86
116
  provider: string;
87
117
  authMethodId?: string | null;
88
118
  status: ConnectorStatus;
@@ -98,12 +128,53 @@ export type ConnectorInstance = {
98
128
  createdAt?: string;
99
129
  updatedAt?: string;
100
130
  };
131
+ export type ConnectorBinding = ConnectorInstance & {
132
+ scopeType: ConnectorScopeType;
133
+ scope: ConnectorScope;
134
+ authorizationMode: ConnectorAuthorizationMode;
135
+ };
136
+ export type ConnectorBindingCreateRequest = {
137
+ scope: ConnectorScope;
138
+ provider: string;
139
+ authorizationMode: ConnectorAuthorizationMode;
140
+ };
141
+ export type ConnectorRuntimeOption = {
142
+ bindingId: string;
143
+ provider: string;
144
+ authorizationMode: ConnectorAuthorizationMode;
145
+ status: ConnectorStatus;
146
+ granted: boolean;
147
+ label: RuntimeI18nText;
148
+ description?: RuntimeI18nText;
149
+ icon?: RuntimeCapabilityIcon;
150
+ /** Sanitized authentication forms needed to connect the current user's account. */
151
+ authMethods?: ConnectorAuthMethodDefinition[];
152
+ profile?: ConnectorProfile | null;
153
+ };
154
+ export type ConnectorRuntimeOptions = {
155
+ scope: ConnectorScope;
156
+ items: ConnectorRuntimeOption[];
157
+ };
158
+ export type ConnectorPersonalAccountInstance = {
159
+ id: string;
160
+ provider: string;
161
+ status: ConnectorStatus;
162
+ authMethodId?: string | null;
163
+ profile?: ConnectorProfile | null;
164
+ scopes?: string[];
165
+ expiresAt?: string | null;
166
+ connectedAt?: string | null;
167
+ disconnectedAt?: string | null;
168
+ lastError?: string | null;
169
+ };
101
170
  export type ConnectorOAuthStartRequest = {
102
171
  app?: ConnectorAppCredentialPayload;
103
172
  };
104
173
  export type ConnectorConnectRequest = {
105
174
  authMethodId?: string;
106
175
  values?: ConnectorAppCredentialPayload;
176
+ /** Assistant proving run access when a non-member authorizes a personal Workspace connector. */
177
+ xpertId?: string;
107
178
  /** @deprecated Use values instead. */
108
179
  app?: ConnectorAppCredentialPayload;
109
180
  };
@@ -122,6 +193,8 @@ export type ConnectorOAuthStartResponse = {
122
193
  };
123
194
  export type ConnectorOAuthStatusResponse = {
124
195
  connector: ConnectorInstance;
196
+ /** Whether this binding currently has a usable credential for the requesting user. */
197
+ granted?: boolean;
125
198
  authorizationUrl?: string | null;
126
199
  stateExpiresAt?: string | null;
127
200
  pollIntervalSeconds?: number | null;
@@ -129,7 +202,11 @@ export type ConnectorOAuthStatusResponse = {
129
202
  };
130
203
  export type ConnectorRuntimeCredential = {
131
204
  connectorId: string;
132
- workspaceId: string;
205
+ bindingId: string;
206
+ scope: ConnectorScope;
207
+ authorizationMode: ConnectorAuthorizationMode;
208
+ workspaceId?: string | null;
209
+ projectId?: string | null;
133
210
  provider: string;
134
211
  appId: string;
135
212
  brand?: string;
@@ -140,7 +217,11 @@ export type ConnectorRuntimeCredential = {
140
217
  };
141
218
  export type ConnectorRuntimeCredentialV2 = {
142
219
  connectorId: string;
143
- workspaceId: string;
220
+ bindingId: string;
221
+ scope: ConnectorScope;
222
+ authorizationMode: ConnectorAuthorizationMode;
223
+ workspaceId?: string | null;
224
+ projectId?: string | null;
144
225
  provider: string;
145
226
  authMethodId: string;
146
227
  credentials: Record<string, unknown>;
@@ -149,8 +230,12 @@ export type ConnectorRuntimeCredentialV2 = {
149
230
  profile?: ConnectorProfile | null;
150
231
  };
151
232
  export type ConnectorRuntimeGetInput = {
152
- workspaceId: string;
153
- provider: string;
233
+ bindingId?: string;
234
+ /** @deprecated Use bindingId. */
235
+ workspaceId?: string;
236
+ projectId?: string;
237
+ provider?: string;
238
+ /** @deprecated Use bindingId. */
154
239
  connectorId?: string;
155
240
  };
156
241
  export interface ConnectorRuntimeApi {
@@ -261,6 +346,12 @@ export type ConnectorCredentialRefreshInput = {
261
346
  authMethodId: string;
262
347
  credential: ConnectorCredential;
263
348
  };
349
+ export type ConnectorCredentialRevokeReason = 'disconnect' | 'delete' | 'rotate';
350
+ export type ConnectorCredentialRevokeInput = {
351
+ authMethodId: string;
352
+ credential: ConnectorCredential;
353
+ reason: ConnectorCredentialRevokeReason;
354
+ };
264
355
  export type ConnectorRuntimeCredentialResolveInput = {
265
356
  authMethodId: string;
266
357
  credential: ConnectorCredential;
@@ -295,6 +386,11 @@ export interface ConnectorStrategyRuntime {
295
386
  exchangeAuthorizationCode?(input: ConnectorAuthorizationCodeInput): Promise<ConnectorCredential>;
296
387
  pollConnection?(input: ConnectorConnectionPollInput): Promise<ConnectorConnectionPollResult>;
297
388
  refreshConnectionCredential?(input: ConnectorCredentialRefreshInput): Promise<ConnectorCredential>;
389
+ /**
390
+ * Revokes a provider-side credential before the host destroys a shared credential locally.
391
+ * Implementations should be idempotent. Hosts remain compatible with providers that omit this hook.
392
+ */
393
+ revokeCredential?(input: ConnectorCredentialRevokeInput): Promise<void>;
298
394
  resolveRuntimeCredential?(input: ConnectorRuntimeCredentialResolveInput): Promise<Record<string, unknown>> | Record<string, unknown>;
299
395
  buildAuthorizationUrl?(input: ConnectorAuthorizationUrlInput): Promise<ConnectorAuthorizationUrlResult>;
300
396
  exchangeOAuthCode?(input: ConnectorOAuthCodeInput): Promise<ConnectorOAuthCredential>;
@@ -310,3 +406,4 @@ export interface ConnectorMultiAuthStrategy extends ConnectorStrategyRuntime {
310
406
  definition: ConnectorMultiAuthDefinition;
311
407
  connect(input: ConnectorConnectInput): Promise<ConnectorConnectResult>;
312
408
  }
409
+ export {};
@@ -1,18 +1,37 @@
1
1
  import { DocumentInterface } from '@langchain/core/documents';
2
2
  import { BaseChatModel } from '@langchain/core/language_models/chat_models';
3
3
  import { IDocumentUnderstandingProvider, IKnowledgeDocument } from '@xpert-ai/contracts';
4
+ import type { JSONValue } from '@xpert-ai/contracts';
4
5
  import { Permissions, XpFileSystem } from '../../core/index';
5
6
  import { ChunkMetadata } from '../types';
6
7
  export type TImageUnderstandingConfig = {
7
8
  stage: 'test' | 'prod';
8
- visionModel: BaseChatModel;
9
+ /**
10
+ * Host-resolved vision model. Strategies that declare that the current
11
+ * configuration does not need vision may receive no model.
12
+ */
13
+ visionModel?: BaseChatModel;
9
14
  permissions?: {
10
15
  fileSystem?: XpFileSystem;
11
16
  };
12
17
  };
18
+ export type TImageUnderstandingMetadata = {
19
+ /**
20
+ * Optional, JSON-safe metadata merged into the owning Knowledge document.
21
+ *
22
+ * Strategies must not place raw file bytes, vectors, credentials, or
23
+ * unrestricted OCR transcripts here. The host persists this value only at
24
+ * the document boundary so downstream plugins can inspect processing
25
+ * outcomes without parsing retrieval chunks.
26
+ */
27
+ documentMetadata?: Record<string, JSONValue>;
28
+ /** Provider-specific, non-persistent warnings consumed by the host. */
29
+ warnings?: unknown;
30
+ [key: string]: unknown;
31
+ };
13
32
  export type TImageUnderstandingResult = {
14
33
  chunks: DocumentInterface<Partial<ChunkMetadata>>[];
15
- metadata: any;
34
+ metadata?: TImageUnderstandingMetadata;
16
35
  };
17
36
  export interface IImageUnderstandingStrategy<TConfig extends TImageUnderstandingConfig = TImageUnderstandingConfig> {
18
37
  readonly permissions: Permissions;
@@ -24,6 +43,15 @@ export interface IImageUnderstandingStrategy<TConfig extends TImageUnderstanding
24
43
  * Validate the configuration
25
44
  */
26
45
  validateConfig(config: TConfig): Promise<void>;
46
+ /**
47
+ * Declares whether this invocation needs the host to resolve a vision model.
48
+ *
49
+ * The default is `true` for backwards compatibility. This hook is evaluated
50
+ * before model resolution so strategies can support deterministic branches,
51
+ * such as rebuilding retrieval text from trusted user-provided metadata,
52
+ * without depending on model availability.
53
+ */
54
+ requiresVisionModel?(config: Readonly<Partial<TConfig>>): boolean | Promise<boolean>;
27
55
  /**
28
56
  * Understand image files (e.g., OCR, VLM, Chart Parsing)
29
57
  */
@@ -1,4 +1,5 @@
1
1
  import { type I18nObject, JSONValue } from '@xpert-ai/contracts';
2
+ import type { WorkspacePortableFileReference } from './workspace-files';
2
3
  export type KnowledgebaseDocumentFile = {
3
4
  buffer: Buffer;
4
5
  originalname?: string;
@@ -148,6 +149,16 @@ export type KnowledgebaseStartProcessingInput = {
148
149
  knowledgebaseId?: string;
149
150
  documentIds: string[];
150
151
  };
152
+ /**
153
+ * Re-runs authorized Knowledge documents with a replacement parser contract.
154
+ * The host resolves tenant and organization scope from the current runtime;
155
+ * callers cannot move documents between Knowledge bases through this API.
156
+ */
157
+ export type KnowledgebaseReprocessDocumentsInput = {
158
+ knowledgebaseId: string;
159
+ documentIds: string[];
160
+ parserConfig: KnowledgebaseDocumentParserConfig;
161
+ };
151
162
  export type KnowledgebaseDocumentStatusInput = {
152
163
  knowledgebaseId?: string;
153
164
  documentIds: string[];
@@ -165,6 +176,29 @@ export type KnowledgebaseDeleteDocumentsResult = {
165
176
  deletedDocumentCount: number;
166
177
  missingDocumentIds?: string[];
167
178
  };
179
+ /** Identifies one standalone image document inside an already authorized Knowledge base. */
180
+ export type KnowledgebaseReadImageInput = {
181
+ knowledgebaseId: string;
182
+ documentId: string;
183
+ };
184
+ /**
185
+ * Server-only image payload for plugin middleware.
186
+ *
187
+ * The `reference` is suitable for governed file flows, while `buffer` exists
188
+ * only for server-side validation or copying. Never expose either value
189
+ * directly to a model or iframe.
190
+ */
191
+ export type KnowledgebaseReadImageResult = {
192
+ knowledgebaseId: string;
193
+ documentId: string;
194
+ name: string;
195
+ mimeType: string;
196
+ size: number;
197
+ sourceHash?: string | null;
198
+ /** Scoped browser/file resolver reference. Never expose it to a model. */
199
+ reference: WorkspacePortableFileReference;
200
+ buffer: Buffer;
201
+ };
168
202
  export interface KnowledgebaseDocumentsApi {
169
203
  listDocuments(input: KnowledgebaseListDocumentsInput): Promise<KnowledgebaseListDocumentsResult>;
170
204
  createFolder(input: KnowledgebaseCreateFolderInput): Promise<KnowledgebaseCreateFolderResult>;
@@ -173,7 +207,10 @@ export interface KnowledgebaseDocumentsApi {
173
207
  importArchive(input: KnowledgebaseImportArchiveInput): Promise<KnowledgebaseImportArchiveResult>;
174
208
  createDocuments(input: KnowledgebaseCreateDocumentsInput): Promise<KnowledgebaseCreateDocumentsResult>;
175
209
  startProcessing(input: KnowledgebaseStartProcessingInput): Promise<KnowledgebaseDocumentStatusResult>;
210
+ reprocessDocuments(input: KnowledgebaseReprocessDocumentsInput): Promise<KnowledgebaseDocumentStatusResult>;
176
211
  getDocumentStatus(input: KnowledgebaseDocumentStatusInput): Promise<KnowledgebaseDocumentStatusResult>;
177
212
  deleteDocuments(input: KnowledgebaseDeleteDocumentsInput): Promise<KnowledgebaseDeleteDocumentsResult>;
213
+ /** Reads original bytes after the host revalidates Knowledge and document scope. */
214
+ readImage(input: KnowledgebaseReadImageInput): Promise<KnowledgebaseReadImageResult>;
178
215
  }
179
216
  export declare const KnowledgebaseDocumentsRuntimeCapability: import("../../core/runtime-capability").RuntimeCapabilityKey<KnowledgebaseDocumentsApi>;
@@ -38,6 +38,7 @@ export type KnowledgebaseListItem = {
38
38
  id: string;
39
39
  name?: string;
40
40
  description?: string | null;
41
+ applicationTags?: string[];
41
42
  type?: string | null;
42
43
  status?: string | null;
43
44
  permission?: string | null;
@@ -1,13 +1,23 @@
1
1
  /** Lifecycle states that plugin-managed Projects may synchronize to the platform. */
2
2
  export type ProjectProvisioningStatus = 'active' | 'archived';
3
+ /** Portable identity of one required, direct External Assistant binding. */
4
+ export type ProjectExternalAssistantExpectation = {
5
+ pluginName: string;
6
+ templateKey: string;
7
+ agentKey: string;
8
+ };
3
9
  /** Stable identity and desired state for an idempotently provisioned Chat Project. */
4
10
  export type ProjectEnsureInput = {
5
11
  /** Caller-generated id reused across retries to prevent duplicate Projects. */
6
12
  projectId: string;
7
- /** Workspace that owns both the Project and connected Assistant. */
8
- workspaceId: string;
13
+ /** @deprecated Projects no longer belong to a Workspace. Accepted only for legacy callers. */
14
+ workspaceId?: string;
9
15
  /** Assistant that must be connected to the Project. */
10
16
  xpertId: string;
17
+ /** Primary requester Agent used as the trust anchor for direct External Assistants. */
18
+ requesterAgentKey?: string;
19
+ /** Portable External Assistant identities that must all validate before any Project mutation. */
20
+ externalAssistantExpectations?: ProjectExternalAssistantExpectation[];
11
21
  /** Current business-project display name. */
12
22
  name: string;
13
23
  /** Current business-project lifecycle state. */
@@ -16,7 +26,8 @@ export type ProjectEnsureInput = {
16
26
  /** Effective Project state after an idempotent ensure operation. */
17
27
  export type ProjectEnsureResult = {
18
28
  projectId: string;
19
- workspaceId: string;
29
+ /** @deprecated Echoed only when supplied by a legacy caller. */
30
+ workspaceId?: string;
20
31
  /** Complete set of Assistants connected after synchronization. */
21
32
  xpertIds: string[];
22
33
  /** Whether this call inserted the Project or reconciled an existing one. */
@@ -1,5 +1,5 @@
1
1
  /** Logical workspace volume catalog supported by plugin-facing file APIs. */
2
- export type WorkspaceFileCatalog = 'projects' | 'users' | 'knowledges' | 'skills' | 'xperts';
2
+ export type WorkspaceFileCatalog = 'projects' | 'users' | 'knowledges' | 'skills' | 'xperts' | 'user-xperts';
3
3
  /** Stable source identifier for portable workspace file references. */
4
4
  export declare const WORKSPACE_FILES_SOURCE: "platform.workspace.files";
5
5
  /**
@@ -31,6 +31,8 @@ export type SandboxProviderCreateOptions = {
31
31
  * Explicit mapping between the server-visible volume root and the sandbox-visible workspace root.
32
32
  */
33
33
  workspaceBinding?: SandboxWorkspaceBinding;
34
+ /** Trusted Project scope hint for providers that can enforce read-only Project Content. */
35
+ protectProjectContent?: true;
34
36
  /**
35
37
  * Canonical sandbox environment identifier that owns the container lifecycle.
36
38
  */
@@ -68,9 +70,15 @@ export type SandboxProviderCreateOptions = {
68
70
  id: string;
69
71
  };
70
72
  };
73
+ export type SandboxProviderCapabilities = {
74
+ /** The provider enforces project.md and skills as read-only inside the runtime. */
75
+ projectContentReadOnly: boolean;
76
+ };
71
77
  export interface ISandboxProvider<T extends SandboxBackendProtocol = SandboxBackendProtocol> {
72
78
  type: string;
73
79
  meta: TSandboxProviderMeta;
80
+ /** Optional for backward compatibility; protected requests treat absence as unsupported. */
81
+ readonly capabilities?: SandboxProviderCapabilities;
74
82
  /**
75
83
  * Whether this provider is currently available in this deployment.
76
84
  * Providers without an availability hook remain available for backward compatibility.
@@ -4,7 +4,8 @@ import { I18nObject, IXpertToolset, ToolProviderCredentials, TToolCredentials, T
4
4
  import { Logger } from '@nestjs/common';
5
5
  import { CommandBus, QueryBus } from '@nestjs/cqrs';
6
6
  import { BaseToolset } from './toolset';
7
- import type { AgentMiddlewareModelProviderConnection, AgentMiddlewareRuntimeApi } from '../agent/middleware/runtime';
7
+ import type { AgentMiddlewareModelProviderConnection, AgentMiddlewareRuntimeApi, AgentMiddlewareRuntimeScope } from '../agent/middleware/runtime';
8
+ import type { RuntimeCapabilityResolver } from '../core/runtime-capability';
8
9
  import type { ManagedQueueService } from '../managed-queue';
9
10
  import type { McpCapabilityDefinitions, McpCapabilityRuntimeProvider } from '../mcp';
10
11
  /**
@@ -34,6 +35,10 @@ export type TBuiltinToolsetParams = TToolsetParams & {
34
35
  queryBus: QueryBus;
35
36
  store?: BaseStore;
36
37
  modelRuntime?: TToolModelRuntime;
38
+ /** Host-bound capabilities for this execution; these override installation-level plugin capabilities. */
39
+ runtimeCapabilities?: RuntimeCapabilityResolver;
40
+ /** Authoritative execution scope used by scoped capabilities and delayed plugin jobs. */
41
+ runtimeScope?: AgentMiddlewareRuntimeScope;
37
42
  managedQueue?: ManagedQueueService;
38
43
  /** Installation scope used to route jobs back to this plugin instance. */
39
44
  pluginScopeKey?: string;
@@ -18,9 +18,8 @@ export type ModelProviderBuiltinToolsetOptions = {
18
18
  */
19
19
  export declare abstract class ModelProviderBuiltinToolset<T extends StructuredToolInterface = StructuredToolInterface, C = TToolCredentials> extends BuiltinToolset<T, C> {
20
20
  private readonly modelProviderOptions;
21
- private readonly runtimeCapabilities?;
22
21
  private modelProvider?;
23
- constructor(modelProviderOptions: ModelProviderBuiltinToolsetOptions, toolset?: IXpertToolset, runtimeCapabilities?: RuntimeCapabilityResolver, params?: TBuiltinToolsetParams);
22
+ constructor(modelProviderOptions: ModelProviderBuiltinToolsetOptions, toolset?: IXpertToolset, _runtimeCapabilities?: RuntimeCapabilityResolver, params?: TBuiltinToolsetParams);
24
23
  _validateCredentials(_credentials: C): Promise<void>;
25
24
  protected getModelProviderRuntime(): Promise<TToolModelProviderRuntime>;
26
25
  protected getModelProviderCredential(modelProvider: TToolModelProviderRuntime): string;