> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xpertai.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# Workspace Files Runtime

> Read, write, resolve, understand, and search files in Xpert workspace volumes.

`WorkspaceFilesRuntimeCapability` exposes `WorkspaceFilesApi` under the stable ID `platform.workspace.files`. It is the plugin-facing file boundary for Xpert workspace Volumes.

Use this capability instead of reading host filesystem paths or implementing plugin-owned storage. It preserves platform scope, returns portable references for asynchronous work, and integrates existing files with the platform file-understanding pipeline.

## Catalogs and scope

The supported logical catalogs are:

```ts theme={null}
type WorkspaceFileCatalog =
  | 'projects'
  | 'users'
  | 'knowledges'
  | 'skills'
  | 'xperts'
```

Explicit APIs accept `WorkspaceFileScope` fields such as `tenantId`, `organizationId`, `userId`, `catalog`, `scopeId`, `projectId`, `knowledgeId`, `rootId`, and `xpertId`. Runtime-aware APIs infer the current Agent workspace when possible.

`filePath` is always relative to a workspace Volume. It is not `/workspace/...` and is never a host/API-process filesystem path.

## Choose the right reference

| Type                             | Use                                                                                                             |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `WorkspaceFileReference`         | Address a known file with explicit scope and a Volume-relative `filePath`.                                      |
| `WorkspaceRuntimeFileDescriptor` | Accept paths and metadata produced by Agent tools, including `/workspace/...` aliases.                          |
| `WorkspacePortableFileReference` | Persist or enqueue a scope-aware reference for a later callback, queue retry, Artifact version, or Sandbox Job. |
| `WorkspaceFileLocator`           | Accept a string, runtime descriptor, or portable reference in a runtime-aware API.                              |

A portable reference has `source: 'platform.workspace.files'`, a stable `filePath`, scope metadata, and a runtime-facing `workspacePath`. Persist the complete reference; do not reduce it to a sandbox path.

## File operations

| Method                           | Result                           | Use                                                         |
| -------------------------------- | -------------------------------- | ----------------------------------------------------------- |
| `uploadBuffer(input)`            | `WorkspaceFile`                  | Upload bytes into an explicitly scoped Volume.              |
| `resolveFile(input)`             | `WorkspaceFile`                  | Resolve metadata and an openable URL without loading bytes. |
| `readBuffer(input)`              | `WorkspaceFileBuffer`            | Read bytes from an explicitly scoped file.                  |
| `deleteFile(input)`              | `void`                           | Delete an explicitly scoped file.                           |
| `resolveRuntimeReference(input)` | `WorkspacePortableFileReference` | Normalize a runtime locator without reading bytes.          |
| `readRuntimeBuffer(input)`       | `WorkspaceRuntimeFileBuffer`     | Resolve and read a locator in the current Agent workspace.  |
| `writeRuntimeBuffer(input)`      | `WorkspaceFile` plus `reference` | Write generated bytes into the current runtime workspace.   |

Read a path received from an Agent tool:

```ts theme={null}
import { WorkspaceFilesRuntimeCapability } from '@xpert-ai/plugin-sdk'

const files = context.runtime.capabilities?.require(
  WorkspaceFilesRuntimeCapability
)

if (!files) throw new Error('Workspace Files is unavailable')

const input = await files.readRuntimeBuffer('/workspace/input/specification.pdf')

console.log(input.mimeType, input.size)
// input.buffer contains the bytes for this operation.
// input.reference can be persisted or sent to a background job.
```

Write a generated result:

```ts theme={null}
const output = await files.writeRuntimeBuffer({
  buffer: reportBuffer,
  originalName: 'quality-report.pdf',
  mimeType: 'application/pdf',
  folder: 'reports',
  metadata: {
    resourceType: 'inspection',
    resourceId: inspectionId
  }
})

await queue.enqueue({
  // Store output.reference in the typed queue payload, not output.buffer.
})
```

## File understanding

The understanding APIs reuse the platform FileAsset and FileChunk index. They do not create a plugin-owned duplicate index.

| Method                                   | Use                                                                          |
| ---------------------------------------- | ---------------------------------------------------------------------------- |
| `understandFile(input)`                  | Register an existing workspace file for parsing and semantic indexing.       |
| `getUnderstandingStatus(input)`          | Read compact parse and vector-index readiness without returning parsed text. |
| `retryUnderstanding(input)`              | Retry parsing and indexing for one failed FileAsset.                         |
| `listUnderstandingChunks(input)`         | Page through bounded chunks in parser order.                                 |
| `searchUnderstandingChunks(input)`       | Run hybrid search against the existing chunk index.                          |
| `validateUnderstandingReferences(input)` | Validate bounded `fileAssetId`/`chunkId` evidence and obtain excerpts.       |

Register and search a file:

```ts theme={null}
const understood = await files.understandFile({
  catalog: 'projects',
  projectId,
  filePath: uploaded.filePath,
  originalName: uploaded.name,
  mimeType: uploaded.mimeType,
  purpose: 'workspace',
  parseMode: 'deep'
})

const status = await files.getUnderstandingStatus({
  catalog: 'projects',
  projectId,
  fileAssetId: understood.fileAssetId
})

if (status.vectorIndexStatus === 'ready') {
  const chunks = await files.searchUnderstandingChunks({
    catalog: 'projects',
    projectId,
    fileAssetId: understood.fileAssetId,
    query: 'acceptance criteria for operating pressure',
    limit: 8,
    contentLength: 1200
  })
}
```

`listUnderstandingChunks()` is one-based and returns `hasMore`. The host clamps page sizes, search limits, excerpt lengths, and per-chunk content lengths. Consumers must page rather than assume a full document is returned.

`vectorIndexStatus` is `pending`, `ready`, `failed`, or `unavailable`. Check it separately from the general parse `status` before exposing semantic search.

`WorkspaceMediaFilesApi<TLocator>` is a narrower type for media-generation adapters. It requires `uploadBuffer()` and `readBuffer()` and optionally exposes `readRuntimeBuffer()` and `deleteFile()`; use it when a component should not depend on the complete Workspace Files API.

## Safety and lifecycle

* Prefer `resolveFile()` when only metadata or an openable URL is required; use byte-reading methods only for actual processing.
* Never pass `/workspace/...` paths into a delayed job. Convert them with `resolveRuntimeReference()` first.
* Validate stored evidence with `validateUnderstandingReferences()` before presenting or acting on it.
* Scope every explicit operation. Do not construct `filePath` from an untrusted absolute path.
* Raw `Buffer` values belong only to the current server operation. Persist portable references for later work.
