@xpert-ai/plugin-spaces 0.2.0 → 0.3.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/ai.d.ts +10 -0
- package/dist/ai.js +2 -2
- package/dist/catalog.d.ts +196 -0
- package/dist/catalog.js +140 -0
- package/dist/content-backup.d.ts +7 -0
- package/dist/content-backup.js +35 -0
- package/dist/content-coverage.d.ts +9 -0
- package/dist/content-coverage.js +12 -0
- package/dist/content-knowledge.d.ts +40 -0
- package/dist/content-knowledge.js +168 -0
- package/dist/documents.d.ts +3 -1
- package/dist/documents.js +22 -3
- package/dist/entities.d.ts +24 -1
- package/dist/entities.js +68 -1
- package/dist/imports.d.ts +4 -4
- package/dist/index.js +4 -1
- package/dist/item-catalog.d.ts +13 -0
- package/dist/item-catalog.js +71 -0
- package/dist/knowledge.d.ts +20 -6
- package/dist/knowledge.js +14 -8
- package/dist/remote/app.css +2 -2
- package/dist/remote/app.js +79 -79
- package/dist/resource-folders.d.ts +7 -0
- package/dist/resource-folders.js +21 -0
- package/dist/resource-provider.d.ts +4 -1
- package/dist/resource-provider.js +19 -3
- package/dist/spaces.js +7 -2
- package/dist/subpages.js +1 -1
- package/dist/view.d.ts +3 -1
- package/dist/view.js +37 -4
- package/package.json +5 -5
package/dist/documents.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { type RuntimeCapabilityRegistry } from '@xpert-ai/plugin-sdk';
|
|
|
2
2
|
import { SpaceAccess } from './access.js';
|
|
3
3
|
import { Space, SpaceItem } from './entities.js';
|
|
4
4
|
import { type SpaceActor } from './domain.js';
|
|
5
|
+
import { type ContentPathCoverage } from './content-coverage.js';
|
|
5
6
|
export declare const contentHash: (buffer: Buffer) => string;
|
|
6
7
|
export declare const safeName: (name: string) => string;
|
|
7
8
|
/** Runtime memory and Space checkpoints are infrastructure, not library content. */
|
|
@@ -17,6 +18,7 @@ export declare class SpaceDocuments {
|
|
|
17
18
|
actor: SpaceActor;
|
|
18
19
|
projectId: string;
|
|
19
20
|
};
|
|
21
|
+
resourceCoverage(actor: SpaceActor, space: Space): Promise<ContentPathCoverage[]>;
|
|
20
22
|
path(actor: SpaceActor, item: SpaceItem): Promise<string>;
|
|
21
23
|
initialize(actor: SpaceActor, space: Space, item: SpaceItem, content?: Buffer): Promise<SpaceItem>;
|
|
22
24
|
/** Register the file on creation/discovery; opening a page never migrates or mutates its model. */
|
|
@@ -32,5 +34,5 @@ export declare class SpaceDocuments {
|
|
|
32
34
|
} | null>;
|
|
33
35
|
private editableMarkdown;
|
|
34
36
|
/** Discover files created by other Assistants without importing hidden version/trash storage. */
|
|
35
|
-
discover(actor: SpaceActor, space: Space, canWrite: boolean): Promise<void>;
|
|
37
|
+
discover(actor: SpaceActor, space: Space, canWrite: boolean, coverage?: ContentPathCoverage[]): Promise<void>;
|
|
36
38
|
}
|
package/dist/documents.js
CHANGED
|
@@ -11,10 +11,11 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
13
|
import { BadRequestException, ConflictException, Inject, Injectable } from '@nestjs/common';
|
|
14
|
-
import { ContentDocumentsRuntimeCapability, ProjectFilesRuntimeCapability, XPERT_RUNTIME_CAPABILITIES_TOKEN } from '@xpert-ai/plugin-sdk';
|
|
14
|
+
import { ContentDocumentsRuntimeCapability, ContentResourcesRuntimeCapability, ProjectFilesRuntimeCapability, XPERT_RUNTIME_CAPABILITIES_TOKEN } from '@xpert-ai/plugin-sdk';
|
|
15
15
|
import { createHash, randomUUID } from 'node:crypto';
|
|
16
16
|
import { SpaceAccess } from './access.js';
|
|
17
17
|
import { denied, scoped } from './domain.js';
|
|
18
|
+
import { contentCoverage, coveredByContent } from './content-coverage.js';
|
|
18
19
|
export const contentHash = (buffer) => createHash('sha256').update(buffer).digest('hex');
|
|
19
20
|
export const safeName = (name) => name.replace(/[\\/\u0000-\u001f]/gu, '_').replace(/^\.+/u, '_').slice(0, 180) || 'Untitled';
|
|
20
21
|
/** Runtime memory and Space checkpoints are infrastructure, not library content. */
|
|
@@ -34,6 +35,24 @@ let SpaceDocuments = class SpaceDocuments {
|
|
|
34
35
|
throw denied();
|
|
35
36
|
return { actor, projectId: space.projectId };
|
|
36
37
|
}
|
|
38
|
+
async resourceCoverage(actor, space) {
|
|
39
|
+
const catalog = this.runtime.require(ContentResourcesRuntimeCapability).catalog;
|
|
40
|
+
const coverage = [];
|
|
41
|
+
for (const deleted of [false, true]) {
|
|
42
|
+
let offset = 0;
|
|
43
|
+
for (;;) {
|
|
44
|
+
const page = await catalog.list({ ...this.scope(actor, space), assistantId: actor.assistantId,
|
|
45
|
+
excludedProviderKeys: ['spaces'], deleted, offset, limit: 100 });
|
|
46
|
+
coverage.push(...contentCoverage(page.items));
|
|
47
|
+
if (!page.hasMore)
|
|
48
|
+
break;
|
|
49
|
+
offset += page.items.length;
|
|
50
|
+
if (!page.items.length)
|
|
51
|
+
throw new Error('spaces.invalid_catalog_page');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return coverage;
|
|
55
|
+
}
|
|
37
56
|
async path(actor, item) {
|
|
38
57
|
const parent = item.parentId ? await this.access.items.findOneByOrFail({ ...scoped(actor), id: item.parentId }) : null;
|
|
39
58
|
if (parent && (parent.kind !== 'folder' || !parent.filePath))
|
|
@@ -101,7 +120,7 @@ let SpaceDocuments = class SpaceDocuments {
|
|
|
101
120
|
}
|
|
102
121
|
}
|
|
103
122
|
/** Discover files created by other Assistants without importing hidden version/trash storage. */
|
|
104
|
-
async discover(actor, space, canWrite) {
|
|
123
|
+
async discover(actor, space, canWrite, coverage = []) {
|
|
105
124
|
if (!space.projectId)
|
|
106
125
|
throw denied();
|
|
107
126
|
const files = await this.api().list({ ...this.scope(actor, space), depth: 12 });
|
|
@@ -110,7 +129,7 @@ let SpaceDocuments = class SpaceDocuments {
|
|
|
110
129
|
return;
|
|
111
130
|
const byPath = new Map(existing.filter((item) => item.filePath && !item.deleted).map((item) => [item.filePath, item]));
|
|
112
131
|
for (const file of files.sort((a, b) => a.path.split('/').length - b.path.split('/').length)) {
|
|
113
|
-
if (isInternalSpacePath(file.path))
|
|
132
|
+
if (isInternalSpacePath(file.path) || coveredByContent(file.path, coverage))
|
|
114
133
|
continue;
|
|
115
134
|
const known = byPath.get(file.path);
|
|
116
135
|
if (known) {
|
package/dist/entities.d.ts
CHANGED
|
@@ -65,4 +65,27 @@ export declare class SpaceFileVersion extends ScopedEntity {
|
|
|
65
65
|
revisionId: string | null;
|
|
66
66
|
sha256: string;
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
/** Organizational placement only. Native resources keep one authoritative provider and
|
|
69
|
+
* stable project bundle; moving a library entry never duplicates business content. */
|
|
70
|
+
export declare class SpaceResourcePlacement extends ScopedEntity {
|
|
71
|
+
spaceId: string;
|
|
72
|
+
contentId: string;
|
|
73
|
+
parentId: string | null;
|
|
74
|
+
version: number;
|
|
75
|
+
}
|
|
76
|
+
/** Disposable revision-bound knowledge state, never a source body or permission cache. */
|
|
77
|
+
export declare class SpaceContentIndex extends ScopedEntity {
|
|
78
|
+
spaceId: string;
|
|
79
|
+
contentId: string;
|
|
80
|
+
revision: string | null;
|
|
81
|
+
bindingRevision: number | null;
|
|
82
|
+
status: 'pending' | 'processing' | 'ready' | 'failed';
|
|
83
|
+
documents: Array<{
|
|
84
|
+
id: string;
|
|
85
|
+
anchor: {
|
|
86
|
+
kind: string;
|
|
87
|
+
id: string;
|
|
88
|
+
};
|
|
89
|
+
}>;
|
|
90
|
+
}
|
|
91
|
+
export declare const entities: (typeof Space | typeof SpaceItem | typeof SpaceFileVersion | typeof SpaceResourcePlacement | typeof SpaceContentIndex)[];
|
package/dist/entities.js
CHANGED
|
@@ -248,4 +248,71 @@ SpaceFileVersion = __decorate([
|
|
|
248
248
|
Index(['tenantId', 'organizationId', 'itemId'])
|
|
249
249
|
], SpaceFileVersion);
|
|
250
250
|
export { SpaceFileVersion };
|
|
251
|
-
|
|
251
|
+
/** Organizational placement only. Native resources keep one authoritative provider and
|
|
252
|
+
* stable project bundle; moving a library entry never duplicates business content. */
|
|
253
|
+
let SpaceResourcePlacement = class SpaceResourcePlacement extends ScopedEntity {
|
|
254
|
+
spaceId;
|
|
255
|
+
contentId;
|
|
256
|
+
parentId;
|
|
257
|
+
version;
|
|
258
|
+
};
|
|
259
|
+
__decorate([
|
|
260
|
+
Column({ type: 'uuid' }),
|
|
261
|
+
__metadata("design:type", String)
|
|
262
|
+
], SpaceResourcePlacement.prototype, "spaceId", void 0);
|
|
263
|
+
__decorate([
|
|
264
|
+
Column({ type: 'uuid' }),
|
|
265
|
+
__metadata("design:type", String)
|
|
266
|
+
], SpaceResourcePlacement.prototype, "contentId", void 0);
|
|
267
|
+
__decorate([
|
|
268
|
+
Column({ type: 'uuid', nullable: true }),
|
|
269
|
+
__metadata("design:type", Object)
|
|
270
|
+
], SpaceResourcePlacement.prototype, "parentId", void 0);
|
|
271
|
+
__decorate([
|
|
272
|
+
Column({ type: 'int', default: 1 }),
|
|
273
|
+
__metadata("design:type", Number)
|
|
274
|
+
], SpaceResourcePlacement.prototype, "version", void 0);
|
|
275
|
+
SpaceResourcePlacement = __decorate([
|
|
276
|
+
Entity('plugin_spaces_resource_placement'),
|
|
277
|
+
Index('IDX_space_resource_placement', ['tenantId', 'organizationId', 'spaceId', 'contentId'], { unique: true })
|
|
278
|
+
], SpaceResourcePlacement);
|
|
279
|
+
export { SpaceResourcePlacement };
|
|
280
|
+
/** Disposable revision-bound knowledge state, never a source body or permission cache. */
|
|
281
|
+
let SpaceContentIndex = class SpaceContentIndex extends ScopedEntity {
|
|
282
|
+
spaceId;
|
|
283
|
+
contentId;
|
|
284
|
+
revision;
|
|
285
|
+
bindingRevision;
|
|
286
|
+
status;
|
|
287
|
+
documents;
|
|
288
|
+
};
|
|
289
|
+
__decorate([
|
|
290
|
+
Column({ type: 'uuid' }),
|
|
291
|
+
__metadata("design:type", String)
|
|
292
|
+
], SpaceContentIndex.prototype, "spaceId", void 0);
|
|
293
|
+
__decorate([
|
|
294
|
+
Column({ type: 'uuid' }),
|
|
295
|
+
__metadata("design:type", String)
|
|
296
|
+
], SpaceContentIndex.prototype, "contentId", void 0);
|
|
297
|
+
__decorate([
|
|
298
|
+
Column({ type: 'varchar', length: 256, nullable: true }),
|
|
299
|
+
__metadata("design:type", Object)
|
|
300
|
+
], SpaceContentIndex.prototype, "revision", void 0);
|
|
301
|
+
__decorate([
|
|
302
|
+
Column({ type: 'int', nullable: true }),
|
|
303
|
+
__metadata("design:type", Object)
|
|
304
|
+
], SpaceContentIndex.prototype, "bindingRevision", void 0);
|
|
305
|
+
__decorate([
|
|
306
|
+
Column({ type: 'varchar', length: 24, default: 'pending' }),
|
|
307
|
+
__metadata("design:type", String)
|
|
308
|
+
], SpaceContentIndex.prototype, "status", void 0);
|
|
309
|
+
__decorate([
|
|
310
|
+
Column({ type: 'jsonb', default: () => "'[]'::jsonb" }),
|
|
311
|
+
__metadata("design:type", Array)
|
|
312
|
+
], SpaceContentIndex.prototype, "documents", void 0);
|
|
313
|
+
SpaceContentIndex = __decorate([
|
|
314
|
+
Entity('plugin_spaces_content_index'),
|
|
315
|
+
Index('IDX_space_content_index', ['tenantId', 'organizationId', 'spaceId', 'contentId'], { unique: true })
|
|
316
|
+
], SpaceContentIndex);
|
|
317
|
+
export { SpaceContentIndex };
|
|
318
|
+
export const entities = [Space, SpaceItem, SpaceFileVersion, SpaceResourcePlacement, SpaceContentIndex];
|
package/dist/imports.d.ts
CHANGED
|
@@ -28,18 +28,18 @@ export declare const importSelection: z.ZodObject<{
|
|
|
28
28
|
spaceId: string;
|
|
29
29
|
parentId: string | null;
|
|
30
30
|
expectedHash: string;
|
|
31
|
+
expectedRevision: string;
|
|
32
|
+
requestId: string;
|
|
31
33
|
bindingId: string;
|
|
32
34
|
locator: string;
|
|
33
|
-
requestId: string;
|
|
34
|
-
expectedRevision: string;
|
|
35
35
|
confirmed: true;
|
|
36
36
|
}, {
|
|
37
37
|
spaceId: string;
|
|
38
38
|
expectedHash: string;
|
|
39
|
+
expectedRevision: string;
|
|
40
|
+
requestId: string;
|
|
39
41
|
bindingId: string;
|
|
40
42
|
locator: string;
|
|
41
|
-
requestId: string;
|
|
42
|
-
expectedRevision: string;
|
|
43
43
|
confirmed: true;
|
|
44
44
|
parentId?: string | null | undefined;
|
|
45
45
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
+
import { SpaceItemCatalog } from './item-catalog.js';
|
|
8
|
+
import { SpaceCatalog } from './catalog.js';
|
|
9
|
+
import { SpaceContentKnowledge } from './content-knowledge.js';
|
|
7
10
|
import { SpaceImports } from './imports.js';
|
|
8
11
|
import 'reflect-metadata';
|
|
9
12
|
import { readFileSync } from 'node:fs';
|
|
@@ -32,7 +35,7 @@ let SpacesPlugin = class SpacesPlugin {
|
|
|
32
35
|
SpacesPlugin = __decorate([
|
|
33
36
|
XpertServerPlugin({
|
|
34
37
|
imports: [TypeOrmModule.forFeature(entities)], entities,
|
|
35
|
-
providers: [SpacesCapabilityProvider, SpaceImports, SpaceReferences, SpaceSubpages, SpaceContent, SpaceAccess, SpaceKnowledge, SpaceDocuments, SpacesResourceProvider, SpacesService, SpacePages, SpaceAi, SpaceFiles, SpaceEditors, SpaceArtifacts, SpacesMiddleware, SpacesView]
|
|
38
|
+
providers: [SpaceItemCatalog, SpaceContentKnowledge, SpaceCatalog, SpacesCapabilityProvider, SpaceImports, SpaceReferences, SpaceSubpages, SpaceContent, SpaceAccess, SpaceKnowledge, SpaceDocuments, SpacesResourceProvider, SpacesService, SpacePages, SpaceAi, SpaceFiles, SpaceEditors, SpaceArtifacts, SpacesMiddleware, SpacesView]
|
|
36
39
|
})
|
|
37
40
|
], SpacesPlugin);
|
|
38
41
|
export { SpacesPlugin };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ContentCatalogProvider } from '@xpert-ai/plugin-sdk';
|
|
2
|
+
import { SpaceAccess } from './access.js';
|
|
3
|
+
import { SpaceContentKnowledge } from './content-knowledge.js';
|
|
4
|
+
/** Exposes native SpaceItems to the platform content catalog without copying content.
|
|
5
|
+
* Pages/files retain their identities, file paths and editing protocols. Creation
|
|
6
|
+
* uses the page/upload workflows; discovery rebuilds only derived catalog entries. */
|
|
7
|
+
export declare class SpaceItemCatalog {
|
|
8
|
+
private readonly access;
|
|
9
|
+
private readonly knowledge;
|
|
10
|
+
constructor(access: SpaceAccess, knowledge: SpaceContentKnowledge);
|
|
11
|
+
readonly catalog: ContentCatalogProvider;
|
|
12
|
+
private describe;
|
|
13
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { Injectable } from '@nestjs/common';
|
|
11
|
+
import { In } from 'typeorm';
|
|
12
|
+
import { SpaceAccess } from './access.js';
|
|
13
|
+
import { scoped, denied } from './domain.js';
|
|
14
|
+
import { SpaceContentKnowledge } from './content-knowledge.js';
|
|
15
|
+
const models = {
|
|
16
|
+
page: { typeId: 'xpert.markdown', modelId: 'markdown.tiptap', schemaVersion: '1', editProtocol: { id: 'platform.text-document', version: '1' } },
|
|
17
|
+
file: { typeId: 'xpert.file', modelId: 'platform.file', schemaVersion: '1', editProtocol: { id: 'platform.file.cas', version: '1' } }
|
|
18
|
+
};
|
|
19
|
+
/** Exposes native SpaceItems to the platform content catalog without copying content.
|
|
20
|
+
* Pages/files retain their identities, file paths and editing protocols. Creation
|
|
21
|
+
* uses the page/upload workflows; discovery rebuilds only derived catalog entries. */
|
|
22
|
+
let SpaceItemCatalog = class SpaceItemCatalog {
|
|
23
|
+
access;
|
|
24
|
+
knowledge;
|
|
25
|
+
constructor(access, knowledge) {
|
|
26
|
+
this.access = access;
|
|
27
|
+
this.knowledge = knowledge;
|
|
28
|
+
}
|
|
29
|
+
catalog = {
|
|
30
|
+
types: [
|
|
31
|
+
{ ...models.page, creatable: false, title: { en_US: 'Pages', zh_Hans: '页面' }, implementationKey: 'spaces.page', implementationTitle: { en_US: 'Markdown', zh_Hans: 'Markdown' }, defaultEditorKey: 'markdown.tiptap' },
|
|
32
|
+
{ ...models.file, creatable: false, title: { en_US: 'Files', zh_Hans: '文件' }, implementationKey: 'spaces.file', implementationTitle: { en_US: 'File', zh_Hans: '文件' }, defaultEditorKey: 'platform.file' }
|
|
33
|
+
],
|
|
34
|
+
discover: async (input) => {
|
|
35
|
+
const space = await this.access.spaces.findOneBy({ ...scoped(input.actor), projectId: input.projectId, deleted: false });
|
|
36
|
+
if (!space)
|
|
37
|
+
return { resourceIds: [] };
|
|
38
|
+
await this.access.project({ ...input.actor, assistantId: input.assistantId }, input.projectId);
|
|
39
|
+
const offset = Number(input.cursor ?? 0);
|
|
40
|
+
if (!Number.isSafeInteger(offset) || offset < 0)
|
|
41
|
+
throw denied();
|
|
42
|
+
const items = await this.access.items.find({ where: { ...scoped(input.actor), spaceId: space.id, kind: In(['page', 'file', 'artifact']), deleted: false }, order: { id: 'ASC' }, skip: offset, take: 100 });
|
|
43
|
+
return { resourceIds: items.filter(item => item.filePath).map(item => item.id), ...(items.length === 100 ? { nextCursor: String(offset + 100) } : {}) };
|
|
44
|
+
},
|
|
45
|
+
describe: input => this.describe(input),
|
|
46
|
+
onResourceReconciled: async (input) => {
|
|
47
|
+
if (input.item.resourceRef.providerKey === 'spaces')
|
|
48
|
+
return;
|
|
49
|
+
const space = await this.access.spaces.findOneBy({ ...scoped(input.actor), projectId: input.projectId, deleted: false });
|
|
50
|
+
if (!space?.knowledgebaseId)
|
|
51
|
+
return;
|
|
52
|
+
const actor = { ...input.actor, projectId: input.projectId, assistantId: input.assistantId };
|
|
53
|
+
await this.access.project(actor, input.projectId, 'write');
|
|
54
|
+
await this.knowledge.refreshItem(actor, space, input.item);
|
|
55
|
+
},
|
|
56
|
+
create: async () => { throw denied(); }
|
|
57
|
+
};
|
|
58
|
+
async describe(input) {
|
|
59
|
+
const { item, space } = await this.access.resource({ ...input.actor, projectId: input.projectId, assistantId: input.assistantId }, input.sourceResourceId, 'read');
|
|
60
|
+
if (!item?.filePath || item.kind === 'folder')
|
|
61
|
+
throw denied();
|
|
62
|
+
return { ...(item.kind === 'page' ? models.page : models.file), projectId: space.projectId, title: item.title,
|
|
63
|
+
revision: `${item.version}:${item.projectedSequence}:${item.fileHash ?? ''}`, updatedAt: item.updatedAt.toISOString(),
|
|
64
|
+
deleted: item.deleted, source: { kind: 'file', path: item.filePath }, defaultEditorKey: item.editorKey ?? 'platform.file', allowedActions: [] };
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
SpaceItemCatalog = __decorate([
|
|
68
|
+
Injectable(),
|
|
69
|
+
__metadata("design:paramtypes", [SpaceAccess, SpaceContentKnowledge])
|
|
70
|
+
], SpaceItemCatalog);
|
|
71
|
+
export { SpaceItemCatalog };
|
package/dist/knowledge.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { type RuntimeCapabilityRegistry } from '@xpert-ai/plugin-sdk';
|
|
2
|
+
import { SpaceContentKnowledge } from './content-knowledge.js';
|
|
2
3
|
import { SpaceAccess } from './access.js';
|
|
3
4
|
import { type SpaceActor } from './domain.js';
|
|
4
5
|
import { Space, SpaceItem } from './entities.js';
|
|
5
6
|
export declare class SpaceKnowledge {
|
|
6
7
|
private readonly access;
|
|
7
8
|
private readonly runtime;
|
|
8
|
-
|
|
9
|
+
private readonly content;
|
|
10
|
+
constructor(access: SpaceAccess, runtime: RuntimeCapabilityRegistry, content: SpaceContentKnowledge);
|
|
9
11
|
enable(actor: SpaceActor, spaceId: string): Promise<{
|
|
10
12
|
knowledgebaseId: string;
|
|
11
13
|
}>;
|
|
@@ -13,24 +15,36 @@ export declare class SpaceKnowledge {
|
|
|
13
15
|
refresh(actor: SpaceActor, spaceId: string): Promise<{
|
|
14
16
|
knowledgebaseId: string | null;
|
|
15
17
|
mode: string;
|
|
16
|
-
items: {
|
|
18
|
+
items: ({
|
|
19
|
+
itemId: string;
|
|
20
|
+
title: string;
|
|
21
|
+
status: string;
|
|
22
|
+
error: string | null;
|
|
23
|
+
document: null;
|
|
24
|
+
} | {
|
|
17
25
|
itemId: string;
|
|
18
26
|
title: string;
|
|
19
27
|
status: "pending" | "ready" | "failed" | "processing";
|
|
20
28
|
error: string | null;
|
|
21
29
|
document: import("@xpert-ai/plugin-sdk").KnowledgebaseDocumentRecord | null;
|
|
22
|
-
}[];
|
|
30
|
+
})[];
|
|
23
31
|
}>;
|
|
24
32
|
status(actor: SpaceActor, spaceId: string): Promise<{
|
|
25
33
|
knowledgebaseId: string | null;
|
|
26
34
|
mode: string;
|
|
27
|
-
items: {
|
|
35
|
+
items: ({
|
|
36
|
+
itemId: string;
|
|
37
|
+
title: string;
|
|
38
|
+
status: string;
|
|
39
|
+
error: string | null;
|
|
40
|
+
document: null;
|
|
41
|
+
} | {
|
|
28
42
|
itemId: string;
|
|
29
43
|
title: string;
|
|
30
44
|
status: "pending" | "ready" | "failed" | "processing";
|
|
31
45
|
error: string | null;
|
|
32
46
|
document: import("@xpert-ai/plugin-sdk").KnowledgebaseDocumentRecord | null;
|
|
33
|
-
}[];
|
|
47
|
+
})[];
|
|
34
48
|
}>;
|
|
35
49
|
search(actor: SpaceActor, spaceId: string, query: string): Promise<{
|
|
36
50
|
itemId: string;
|
|
@@ -39,5 +53,5 @@ export declare class SpaceKnowledge {
|
|
|
39
53
|
filePath: string;
|
|
40
54
|
hash: string;
|
|
41
55
|
}[]>;
|
|
42
|
-
verify(actor: SpaceActor, itemId: string, hash: string): Promise<boolean>;
|
|
56
|
+
verify(actor: SpaceActor, itemId: string, hash: string, contentId?: string): Promise<boolean>;
|
|
43
57
|
}
|
package/dist/knowledge.js
CHANGED
|
@@ -14,6 +14,7 @@ import { ForbiddenException, Inject, Injectable } from '@nestjs/common';
|
|
|
14
14
|
import { ProjectKnowledgeRuntimeCapability, KnowledgebaseDocumentsRuntimeCapability, KnowledgebaseRuntimeCapability, ProjectFilesRuntimeCapability, XPERT_RUNTIME_CAPABILITIES_TOKEN } from '@xpert-ai/plugin-sdk';
|
|
15
15
|
import { z } from 'zod/v3';
|
|
16
16
|
import { KBDocumentStatusEnum } from '@xpert-ai/contracts';
|
|
17
|
+
import { SpaceContentKnowledge } from './content-knowledge.js';
|
|
17
18
|
import { SpaceAccess } from './access.js';
|
|
18
19
|
import { denied, scoped } from './domain.js';
|
|
19
20
|
const metadata = z.object({ spaceItemId: z.string().uuid(), spaceFileHash: z.string() }).passthrough();
|
|
@@ -21,9 +22,11 @@ const documentMetadata = z.object({ documentId: z.string().uuid() }).passthrough
|
|
|
21
22
|
let SpaceKnowledge = class SpaceKnowledge {
|
|
22
23
|
access;
|
|
23
24
|
runtime;
|
|
24
|
-
|
|
25
|
+
content;
|
|
26
|
+
constructor(access, runtime, content) {
|
|
25
27
|
this.access = access;
|
|
26
28
|
this.runtime = runtime;
|
|
29
|
+
this.content = content;
|
|
27
30
|
}
|
|
28
31
|
async enable(actor, spaceId) {
|
|
29
32
|
const { space } = await this.access.resource(actor, spaceId, 'manage');
|
|
@@ -88,6 +91,7 @@ let SpaceKnowledge = class SpaceKnowledge {
|
|
|
88
91
|
const items = await this.access.items.findBy({ ...scoped(actor), spaceId });
|
|
89
92
|
for (const item of items)
|
|
90
93
|
await this.sync(actor, space, item);
|
|
94
|
+
await this.content.refresh(actor, space);
|
|
91
95
|
return this.status(actor, spaceId);
|
|
92
96
|
}
|
|
93
97
|
async status(actor, spaceId) {
|
|
@@ -108,10 +112,10 @@ let SpaceKnowledge = class SpaceKnowledge {
|
|
|
108
112
|
item.indexStatus = status;
|
|
109
113
|
item.indexError = error;
|
|
110
114
|
}
|
|
111
|
-
return { knowledgebaseId: space.knowledgebaseId, mode: 'keyword', items: items.filter((item) => item.kind !== 'folder' && !item.deleted).map((item) => ({
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
return { knowledgebaseId: space.knowledgebaseId, mode: 'keyword', items: [...await this.content.status(actor, space), ...items.filter((item) => item.kind !== 'folder' && !item.deleted).map((item) => ({
|
|
116
|
+
itemId: item.id, title: item.title, status: item.indexStatus, error: item.indexError,
|
|
117
|
+
document: documents.documents.find((doc) => doc.id === item.knowledgeDocumentId) ?? null
|
|
118
|
+
}))] };
|
|
115
119
|
}
|
|
116
120
|
async search(actor, spaceId, query) {
|
|
117
121
|
const { space } = await this.access.resource(actor, spaceId, 'read');
|
|
@@ -148,9 +152,11 @@ let SpaceKnowledge = class SpaceKnowledge {
|
|
|
148
152
|
continue;
|
|
149
153
|
matches.push({ itemId: item.id, title: item.title, text: document.pageContent, filePath: item.filePath, hash });
|
|
150
154
|
}
|
|
151
|
-
return matches;
|
|
155
|
+
return [...matches, ...await this.content.matches(actor, space, result.documents)];
|
|
152
156
|
}
|
|
153
|
-
async verify(actor, itemId, hash) {
|
|
157
|
+
async verify(actor, itemId, hash, contentId) {
|
|
158
|
+
if (contentId)
|
|
159
|
+
return this.content.verify(actor, contentId, hash);
|
|
154
160
|
const { item, space } = await this.access.resource(actor, itemId, 'read');
|
|
155
161
|
if (!item?.filePath || !space.projectId)
|
|
156
162
|
return false;
|
|
@@ -161,6 +167,6 @@ let SpaceKnowledge = class SpaceKnowledge {
|
|
|
161
167
|
SpaceKnowledge = __decorate([
|
|
162
168
|
Injectable(),
|
|
163
169
|
__param(1, Inject(XPERT_RUNTIME_CAPABILITIES_TOKEN)),
|
|
164
|
-
__metadata("design:paramtypes", [SpaceAccess, Object])
|
|
170
|
+
__metadata("design:paramtypes", [SpaceAccess, Object, SpaceContentKnowledge])
|
|
165
171
|
], SpaceKnowledge);
|
|
166
172
|
export { SpaceKnowledge };
|