Skip to content

Latest commit

 

History

History
360 lines (296 loc) · 20.1 KB

api.md

File metadata and controls

360 lines (296 loc) · 20.1 KB

API reference — 1.1.0

SDK 1.1 adds Node-only release tools: deterministic offline bundles, detached provenance, reviewed updates and upstream comparison. Existing 1.0 stable APIs remain compatible. The complete export/type list is generated in API_SUPPORT.json.

SDK 0.13 adds /testing scenario/clock/fault/trace helpers, /diagnostics local sessions and adapters, and /devtools feature templates plus planPlugin() and generatePluginContracts(). createPluginHost({runtime}), registry runtimes, settings/secret runtime ports, host.inspect() and operator replaceGrants() are optional additions. See testing, diagnostics and development tools for exact limits and ownership.

SDK 0.8 adds optional job storage, history and retry and stored result files. Existing v1 response shapes remain valid.

Workspace client helpers include connection-bound project edit sessions, project.watchFiles(paths, options), client.watchJob(jobId, options) and client.waitForJob(jobId, options). See observation for event shapes, TypeScript types, cancellation and budgets. These are client helpers over the existing workspace protocol; they grant no additional capability.

For project scaffolding, inert diagnostics and supervised local execution, see development tools. For opt-in startCommandJob, getJob, getJobEvents, cancelJob, readJobArtifact, job reporters and budgets, see command jobs. Existing handler options gain an optional job reporter; ordinary executeCommand behavior and short request deadlines are unchanged.

Import portable values and types from @altifigence/dds-plugin-sdk. The core validates plain data, manages plugin lifetimes and dispatches diagnostics, language features, commands and explicit host ports. It performs no Node filesystem, process or network operations. See WORKSPACES for the separate Node server and client, THEMES for XML themes, and PUBLISHING and CONSENT for package review and acceptance.

Manifests and activation

definePlugin(manifest, activate) returns a frozen {manifest, activate} after validating an independent copy. The host calls activate(context); return undefined or a Disposable with dispose(), synchronously or asynchronously. The host owns registration cleanup even if a plugin's disposer throws.

The diagnostics protocol remains 1. Manifest versions 1 and 2 are separate accepted shapes; the manifest schema contains both alternatives. Existing v1 plugins retain the original fields, single identifier license, diagnostics capability, two diagnostics permissions and supportedHosts: ['test-host'].

Version 2 adds runtime, source, commands and workspace permissions:

import { definePlugin } from '@altifigence/dds-plugin-sdk';

export default definePlugin({
  manifestVersion: 2,
  id: 'example-workspace', name: 'Example Workspace', publisher: 'example',
  version: '1.0.0', protocolVersion: 1, entry: './plugin.mjs',
  runtime: 'workspace', capabilities: ['commands'],
  permissions: ['workspace.read', 'workspace.write', 'backend.invoke'],
  supportedHosts: ['test-host', 'workspace-host'],
  license: 'Apache-2.0',
  source: {visibility: 'open', licenseFile: './LICENSE',
    repository: 'https://github.com/example/example-workspace'},
}, context => context.registerCommand({
  id: 'summarize', title: 'Summarize a saved file',
  parameters: [{name: 'path', label: 'File path', type: 'string', required: true}],
}, async (input, {signal}) => {
  const file = await context.workspace.readFile(input.path, {signal});
  return context.backends.invoke('summarize', {content: file.content}, {signal});
}));

Every field shown in this manifest is required except source.repository. IDs and publishers use lowercase letters/digits with ., _, - separators, starting with a letter; version follows SemVer. entry is a relative .mjs path without traversal. createPluginHost() receives an explicitly imported module and does not load that path.

V2 runtime is ui or workspace. UI manifests cannot request workspace.read, workspace.write or backend.invoke. Runtime is compatibility metadata, not an isolation mechanism. source.visibility is open or closed; source.licenseFile is a relative file path, canonicalized without leading ./. An optional repository must use credential-free HTTPS without a query or hash. The parser validates metadata, not file existence or public repository access.

V2 license accepts bounded SPDX-style expression grammar, including AND, OR, WITH, parentheses and LicenseRef- identifiers. For example, MIT OR Apache-2.0 or LicenseRef-Proprietary. parseLicenseExpression() checks syntax; it does not verify SPDX registry membership, copyright ownership, license eligibility or agreement acceptance. See LICENSING.

Activation context member Behavior
host {id: 'test-host' | 'workspace-host', version: '0.13.0', protocolVersion: 1}
pluginId, scope Manifest ID and opaque host {projectId, sessionId}
grants Frozen intersection of host grants and manifest permissions
signal Aborted on deactivation, host disposal or activation timeout
registerDiagnosticsProvider(selector, provider) Require declared diagnostics capability and both effective diagnostics grants
registerLanguageProvider(kind, selector, provider) Require declared feature and effective document.read / language.provide grants
registerCommand(definition, handler) Require declared commands capability; return a registration Disposable
workspace Permission-checked saved-file read, list and CAS write APIs
backends Permission-checked invocation of named, host-configured handlers
settings Plugin/project-scoped effective reads and subscriptions; requires declared capability and grant

createPluginHost() defaults to no grants. createTestHost() from @altifigence/dds-plugin-sdk/testing preserves its v1 compatibility defaults: test-host and both diagnostics grants. Permission declarations do not grant themselves access. A missing optional port returns capability_unavailable.

Commands and parameters

context.registerCommand(definition, handler) takes {id, title, description?, parameters?, inputSchema?, outputSchema?, display?}. Each legacy parameter is {name, label, type, required, choices?}; types are string, number or boolean. choices is a nonempty unique array available only for string parameters. A command supports at most 32 parameters and each string choice has at most 256 code points.

If both parameters and inputSchema are omitted, the input may be any bounded JsonValue. If parameters is present, including an empty array, input must be an object containing only the named parameters. Required values must be supplied, types must match and choices must match exactly. Legacy parameters have no defaults or coercion. New schemas and parameters are mutually exclusive; schemas support validated defaults and output validation. See structured data, settings, secret leases and localized display.

const registration = context.registerCommand({
  id: 'greet', title: 'Say hello',
  parameters: [{name: 'name', label: 'Your name', type: 'string', required: true}],
}, (input, {signal}) => {
  signal.throwIfAborted();
  return {message: `Hello, ${input.name}!`};
});

The host lists immutable metadata with host.listCommands() and calls host.executeCommand(pluginId, commandId, input, {signal?, timeoutMs?}). Handlers return JsonValue or a promise of it. Input and output are copied and bounded; class instances, functions, accessors, symbols, sparse arrays, non-finite numbers and cycles are rejected. Registration disposal aborts its pending calls. Language providers add completion, hover, definition, references and document symbols. Code actions and automatic edit application are not implemented. Client-side project edit sessions save explicitly provided content or text edits with revision checks.

Workspace and backend ports

Plugin method Permission Result
workspace.readFile(path, options?) workspace.read {path, content, revision}
workspace.listFiles(path = '', options?) workspace.read Array of {path, kind: 'file' | 'directory', revision?}
workspace.writeFile(path, content, {expectedRevision, signal?, timeoutMs?}) workspace.write {path, revision}
backends.invoke(id, input, options?) backend.invoke Bounded JsonValue

options means {signal?, timeoutMs?}. Paths use workspace-relative / separators without absolute roots, backslashes, colons, control characters, empty segments or ./... Only listing accepts '' for the root. The portable parser checks syntax; the host port owns containment, symlink policy and the actual allowed root. Listings have unique relative paths, at most 1,000 entries, and results must stay under a requested directory. File results must echo the requested path.

Writes require an explicit compare-and-swap expectation:

const saved = await context.workspace.readFile('notes.txt', {signal});
const changed = await context.workspace.writeFile('notes.txt', 'Updated\n', {
  expectedRevision: saved.revision, signal,
});
const created = await context.workspace.writeFile('new-note.txt', 'New\n', {
  expectedRevision: null, signal,
});

null means create an absent file only. An existing file requires the revision returned by a read. The port must enforce CAS and return conflict after a mismatch; the portable host cannot enforce a filesystem transaction itself. Core revisions are opaque strings of 1–128 code points. The supplied Node workspace uses SHA-256 of exact UTF-8 bytes and has a stricter path policy; see WORKSPACES and the wire protocol.

The host configures backends: {name: handler}. A handler receives (input, {signal, pluginId, scope}) and returns JSON. The plugin chooses only a configured name; it cannot provide an executable, URL or shell command through this API. The Node adapter separately supports operator-configured tools.

Diagnostics

A selector is {languages: ['plaintext'], priority?: 0}. Priority ranges from -100 to 100. Highest priority wins, followed by the earliest active registration. provideDiagnostics(request, {signal}) returns a result or promise. The request contains {protocolVersion: 1, requestId, scope, snapshot}, with snapshot {uri, languageId, modelVersion, workspaceRevision, text}.

The URI identifies supplied document text; it grants no access to that resource. modelVersion is a positive safe integer. Scope/request/revision strings have at most 128 Unicode code points. Use createDiagnosticsResult(request, items) to echo the identity without document text:

return createDiagnosticsResult(request, [{
  range: {start: {line: 0, character: 0}, end: {line: 0, character: 4}},
  severity: 'info', message: 'Resolve this TODO.', code: 'todo', source: 'example',
}]);

Positions use zero-based lines and UTF-16 code-unit offsets. Severity is error, warning, info or hint; messages are plain text. The host checks identity, ordered ranges and endpoints against the supplied CRLF/LF/CR document. Edits, document switches and revision changes invalidate pending results.

Host methods and validators

createPluginHost({hostId?, scope?, grants?, workspace?, backends?}) returns a trusted in-process PluginHost. hostId defaults to test-host; scope defaults to example-project / example-session. Methods are activate, setDocument, requestDiagnostics, requestLanguage, listPlugins, listCommands, executeCommand, deactivate and dispose. See host-contract and testing for runnable host use.

parseManifest, parseDiagnosticsRequest and parseDiagnosticsResult accept plain objects or JSON text. parseDocumentSnapshot and parseCommandDefinition accept plain data objects. parseJsonValue validates a JSON value rather than parsing text. parseWorkspacePath checks path syntax. All structured outputs are independent frozen copies. Runtime checks reject unexpected fields and unsupported object shapes without invoking getters or caller toJSON hooks.

Exported LIMITS value Limit
manifestBytes, commandBytes 16,384 compact UTF-8 JSON bytes each
requestBytes, resultBytes 1,600,000 UTF-8 JSON bytes each
documentBytes, jsonBytes 262,144 UTF-8 bytes each
maxDiagnostics, maxLanguageItems, messageLength 500 diagnostics or language items; 2,048 code points per diagnostic message
maxRegistrations, maxCommands 32 active plugins/providers/backend handlers; 64 commands per host
maxPendingRequests, maxFiles 64 per registry/host operation group; 1,000 listed entries
jsonDepth, jsonNodes Depth 16; 10,000 visited JSON nodes
jsonArrayItems, jsonObjectProperties 1,000 array items; 128 fields per object
defaultTimeoutMs, maxTimeoutMs 5,000 ms default/activation; 30,000 ms maximum request

JSON text budgets count original whitespace. Object budgets use only validated copies. JSON Schema 2020-12 files under schemas/ describe shapes; runtime parsers additionally enforce UTF-8 totals, license expression grammar, request/result identity, ranges and parameter semantics.

Cancellation and errors

Check the supplied AbortSignal before work and between asynchronous steps. Cancellation settles a host request and discards late results. It cannot stop a blocking loop, undo a completed write or revoke ambient process APIs. Activation has a fixed 5-second deadline; request timeoutMs must be an integer 1–30,000.

Catch PluginSdkError and inspect code:

Code Meaning
invalid_contract Invalid fields, parameters, ranges, options or activation return
permission_denied A required effective grant is absent
unsupported_host, version_mismatch Host or diagnostics protocol incompatibility
cancelled, stale_snapshot Caller cancelled, or document identity changed
budget_exceeded Input/output/concurrency limit or timeout
disposed Plugin, registration or host removed
provider_failed, provider_unavailable Plugin failed, or no matching provider exists
capability_unavailable No named command/backend or workspace port exists
conflict Host port rejected a stale file revision

Plugin exception details are masked by the host. Trusted port PluginSdkError codes are preserved with a safe message. The Node wire protocol uses its own WorkspaceError vocabulary; see workspace-protocol.

File revisions and conditional reads

WorkspaceClient adds getFileCapabilities(options?), getFileRevision(path, options?) and readFileIfChanged(path, knownRevision, options?) in 0.6.0. An unchanged conditional result has notModified: true and no content; a changed result has notModified: false and content. knownRevision: null requests content. See file revisions for shapes, fallback and lifecycle rules.

Binary job results

SDK 0.7.0 adds job.addBinaryArtifact(), client.getBinaryArtifactCapabilities(), listJobBinaryArtifacts(), getJobBinaryArtifact() and readJobBinaryArtifactChunk(). The Node downloadJobBinaryArtifact() helper verifies and publishes a complete file, with explicit resumption of a partial download. Contracts and decoders are exported through /artifacts. See binary artifacts for operator opt-in, identity, limits, filesystem behavior and browser responsibilities.

Durable jobs and stored results (SDK 0.8.0)

Use /job-storage and /job-storage-node for committed recovery; /job-history for bounded queries and explicit retry; /artifact-storage and /artifact-storage-node for retained result contracts and bytes. The core host adds artifactStorageCapabilities, listStoredJobArtifacts, getStoredJobArtifact and readStoredJobArtifactChunk. The HTTP client adds the corresponding capability/list/get/chunk methods and readStoredJobArtifactText; /workspace-node exports downloadStoredJobArtifact. Exact parameters and limits are in the declarations and stored-result guide.

Scoped project tools (SDK 0.9.0)

/project-watch and /project-query export pure contracts, validators and limits. /project-watch-node exports createNodeProjectWatcher, and /project-query-node exports createNodeProjectQueries sharing that watcher's scope and lifetime. The Node workspace server optionally accepts projects:{roots,fileSystem:'local'}.

The HTTP client and createWorkspaceProject expose getProjectCapabilities, getProjectSnapshot, listTree, searchFiles, searchText, releaseProjectQuery and watchProject. /workspace-client also exports the transport limits and capability/poll validators. The server's revokeProjects() closes project resources and requires a new generation to re-enable them. Edit sessions retain their own snapshots. See project tools, observation and tree/search.

Bidirectional transfers (SDK 0.10.0)

/artifact-transfer exports browser-safe streamJobBinaryArtifact and streamStoredJobArtifact, incremental SHA-256 and typed sink/verification contracts. /artifact-transfer-browser supplies selected-file and OPFS writable sinks; /artifact-resume-browser adds createOpfsArtifactSink, explicit partial names, checkpoint validation and Worker capability detection. Recovery requires resume: true and independently rehashed local prefix bytes.

/uploads provides contracts and uploadFile; /uploads-node provides the private Node upload store and selected-file source; /uploads-browser adapts an explicit File. The HTTP client adds capability/begin/query/write/commit/abort methods. /transfer-queue exports createTransferQueue, options/snapshot validators, limits, states and phases. See uploads, streaming, queue and persistent recovery.

Language assistance and editing (SDK 0.11.0)

The root import adds signature help, completion resolution/snippets, rename, formatting, code actions, semantic tokens, folding, inlay hints and symbol trees. host.languageCapabilities() describes current features and limits; host.validateLanguageResult(result) checks actual host ownership and currency before painting. Features and modifiers require explicit manifest declarations.

/workspace-edits supplies proposal/preview/receipt contracts, pure preview, reviewed application, observational recovery and explicit inverse proposals. /workspace-edits-node adds an operator-owned intent/receipt journal outside the workspace. Application uses existing conditional file methods and current authorization, with no automatic rollback or retry.

See assistance, workspace edits, formatting/actions and language display for complete contracts, limits and independent examples.

Release tools (1.1, Node only)

See release tools for the complete bundle, Ed25519 provenance, approval/activation journal and upstream candidate APIs. The five entry points provide declarations and versioned schemas without adding SDK runtime dependencies.

Workflows, cache and tools (1.2)

See workflows and cache for DAG plans, per-step command jobs, durable checkpoints, explicit resume and deterministic incremental reuse. Tool streams covers the portable parser and optional Node process runner. LSP maps the public stdio bridge's negotiated subset to existing language contracts. Seven additional exports have declarations and eleven schemas; only the tool-output parser is portable to a browser.