@xpert-ai/plugin-sdk 3.15.10 → 3.15.12
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 +17 -0
- package/README.md +15 -0
- package/collaboration-client.cjs.default.js +1 -0
- package/collaboration-client.cjs.js +12 -0
- package/collaboration-client.cjs.mjs +2 -0
- package/collaboration-client.cjs2.js +406 -0
- package/collaboration-client.d.ts +1 -0
- package/collaboration-client.esm.js +1 -0
- package/collaboration-client.esm2.js +398 -0
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +149 -415
- package/index.cjs.mjs +2 -0
- package/index.esm.js +126 -401
- package/package.json +17 -2
- package/src/collaboration-client.d.ts +3 -0
- package/src/lib/agent/middleware/capabilities/assistant-task.d.ts +1 -0
- package/src/lib/core/runtime-capability.d.ts +1 -0
- package/src/lib/managed-queue/index.d.ts +17 -0
- package/src/lib/runtime/capabilities/artifacts.d.ts +41 -0
- package/src/lib/runtime/capabilities/index.d.ts +1 -0
- package/src/lib/runtime/capabilities/sandbox-jobs.d.ts +142 -0
- package/src/lib/sandbox/index.d.ts +6 -0
- package/src/lib/sandbox/protocol.d.ts +4 -0
- package/src/lib/sandbox/runtime-provider.d.ts +181 -0
- package/src/lib/sandbox/runtime-provider.decorator.d.ts +3 -0
- package/src/lib/sandbox/runtime-provider.registry.d.ts +9 -0
- package/src/lib/sandbox/sandbox.interface.d.ts +40 -0
- package/src/lib/sandbox/workspace-mapper.d.ts +20 -0
- package/src/lib/sandbox/workspace-mapper.decorator.d.ts +3 -0
- package/src/lib/sandbox/workspace-mapper.registry.d.ts +9 -0
- package/src/lib/strategy.d.ts +6 -2
|
@@ -15,6 +15,15 @@ export type PluginJobProcessorMetadata = {
|
|
|
15
15
|
jobName: string;
|
|
16
16
|
concurrency?: number;
|
|
17
17
|
};
|
|
18
|
+
/** Physical worker pool chosen independently from a plugin's logical queue name. */
|
|
19
|
+
export type ManagedQueueExecutionPool = 'default' | 'sandbox-browser';
|
|
20
|
+
/** Readiness signal used to reject work before it is stranded in an unconsumed pool. */
|
|
21
|
+
export type ManagedQueueExecutionPoolHealth = {
|
|
22
|
+
executionPool: ManagedQueueExecutionPool;
|
|
23
|
+
available: boolean;
|
|
24
|
+
workerCount: number;
|
|
25
|
+
warning?: string;
|
|
26
|
+
};
|
|
18
27
|
export type ManagedQueueRemoveOption = boolean | number | {
|
|
19
28
|
age?: number;
|
|
20
29
|
count?: number;
|
|
@@ -47,12 +56,15 @@ export type ManagedQueueEnqueueInput<TPayload = unknown> = {
|
|
|
47
56
|
backoffMs?: ManagedQueueBackoffInput;
|
|
48
57
|
removeOnComplete?: ManagedQueueRemoveOption;
|
|
49
58
|
removeOnFail?: ManagedQueueRemoveOption;
|
|
59
|
+
/** Defaults to `default`; browser-heavy jobs must explicitly select the isolated pool. */
|
|
60
|
+
executionPool?: ManagedQueueExecutionPool;
|
|
50
61
|
};
|
|
51
62
|
export type ManagedQueueEnqueueResult = {
|
|
52
63
|
jobId: string;
|
|
53
64
|
};
|
|
54
65
|
export type ManagedQueueCancelInput = {
|
|
55
66
|
jobId: string;
|
|
67
|
+
executionPool?: ManagedQueueExecutionPool;
|
|
56
68
|
};
|
|
57
69
|
export type ManagedQueueCancelResult = {
|
|
58
70
|
success: boolean;
|
|
@@ -100,7 +112,12 @@ export interface ManagedQueueService {
|
|
|
100
112
|
cancel(input: ManagedQueueCancelInput): Promise<ManagedQueueCancelResult>;
|
|
101
113
|
getJob<TPayload = unknown>(input: {
|
|
102
114
|
jobId: string;
|
|
115
|
+
executionPool?: ManagedQueueExecutionPool;
|
|
103
116
|
}): Promise<ManagedQueueJobSnapshot<TPayload> | null>;
|
|
117
|
+
/** Reports active BullMQ consumers for a physical execution pool. */
|
|
118
|
+
getExecutionPoolHealth(input: {
|
|
119
|
+
executionPool: ManagedQueueExecutionPool;
|
|
120
|
+
}): Promise<ManagedQueueExecutionPoolHealth>;
|
|
104
121
|
getRedis(): Promise<ManagedQueueRedis>;
|
|
105
122
|
}
|
|
106
123
|
export declare function PluginJobProcessor(options: PluginJobProcessorOptions): ClassDecorator;
|
|
@@ -43,6 +43,10 @@ export type ArtifactVersionInput = {
|
|
|
43
43
|
export type CreateArtifactVersionInput = ArtifactVersionInput & {
|
|
44
44
|
artifactId: string;
|
|
45
45
|
};
|
|
46
|
+
/** Idempotently creates or reuses one immutable Artifact content version. */
|
|
47
|
+
export type EnsureArtifactVersionInput = CreateArtifactVersionInput & {
|
|
48
|
+
idempotencyKey: string;
|
|
49
|
+
};
|
|
46
50
|
/** Access policy requested for an Artifact link. */
|
|
47
51
|
export type ArtifactLinkAccessInput = {
|
|
48
52
|
mode: ArtifactAccessMode;
|
|
@@ -66,6 +70,10 @@ export type CreateArtifactLinkInput = {
|
|
|
66
70
|
presentation?: ArtifactLinkPresentationInput | null;
|
|
67
71
|
metadata?: Record<string, unknown> | null;
|
|
68
72
|
};
|
|
73
|
+
/** Stable plugin-owned slot for one active durable share policy. */
|
|
74
|
+
export type ArtifactShareInput = CreateArtifactLinkInput & {
|
|
75
|
+
shareKey: string;
|
|
76
|
+
};
|
|
69
77
|
/** Creates a short-lived signed preview link; never use this as a durable share URL. */
|
|
70
78
|
export type CreateSignedArtifactPreviewLinkInput = Omit<CreateArtifactLinkInput, 'access'> & {
|
|
71
79
|
ttlSeconds?: number | null;
|
|
@@ -76,6 +84,7 @@ export type ArtifactVersionRecord = {
|
|
|
76
84
|
artifactId: string;
|
|
77
85
|
versionNumber: number;
|
|
78
86
|
status: ArtifactVersionStatus;
|
|
87
|
+
idempotencyKey?: string | null;
|
|
79
88
|
sourceVersionId?: string | null;
|
|
80
89
|
checksum?: string | null;
|
|
81
90
|
mimeType: string;
|
|
@@ -84,6 +93,8 @@ export type ArtifactVersionRecord = {
|
|
|
84
93
|
description?: string | null;
|
|
85
94
|
size?: number | null;
|
|
86
95
|
sha256?: string | null;
|
|
96
|
+
workspaceFileRef?: WorkspacePortableFileReference | null;
|
|
97
|
+
metadata?: Record<string, unknown> | null;
|
|
87
98
|
createdAt?: string | Date;
|
|
88
99
|
};
|
|
89
100
|
/** Durable Artifact container returned to plugins. */
|
|
@@ -99,6 +110,7 @@ export type ArtifactRecord = ArtifactScopeInput & {
|
|
|
99
110
|
description?: string | null;
|
|
100
111
|
currentVersionId?: string | null;
|
|
101
112
|
currentVersion?: ArtifactVersionRecord | null;
|
|
113
|
+
metadata?: Record<string, unknown> | null;
|
|
102
114
|
createdAt?: string | Date;
|
|
103
115
|
updatedAt?: string | Date;
|
|
104
116
|
};
|
|
@@ -107,6 +119,7 @@ export type ArtifactLinkRecord = ArtifactScopeInput & {
|
|
|
107
119
|
id: string;
|
|
108
120
|
artifactId: string;
|
|
109
121
|
artifactVersionId?: string | null;
|
|
122
|
+
shareKey?: string | null;
|
|
110
123
|
versionMode: ArtifactLinkVersionMode;
|
|
111
124
|
slug: string;
|
|
112
125
|
publicUrl: string;
|
|
@@ -120,6 +133,7 @@ export type ArtifactLinkRecord = ArtifactScopeInput & {
|
|
|
120
133
|
disposition: ArtifactLinkDisposition;
|
|
121
134
|
allowDownload: boolean;
|
|
122
135
|
safeHtmlProfile?: ArtifactSafeHtmlProfile | null;
|
|
136
|
+
metadata?: Record<string, unknown> | null;
|
|
123
137
|
createdAt?: string | Date;
|
|
124
138
|
updatedAt?: string | Date;
|
|
125
139
|
artifact?: ArtifactRecord;
|
|
@@ -140,6 +154,27 @@ export type ListArtifactsResult = {
|
|
|
140
154
|
page: number;
|
|
141
155
|
pageSize: number;
|
|
142
156
|
};
|
|
157
|
+
export type FindArtifactBySourceInput = Pick<ArtifactSourceInput, 'pluginName' | 'resourceType' | 'resourceId'> & {
|
|
158
|
+
includeDeleted?: boolean | null;
|
|
159
|
+
};
|
|
160
|
+
export type ListArtifactVersionsInput = {
|
|
161
|
+
artifactId: string;
|
|
162
|
+
idempotencyKey?: string | null;
|
|
163
|
+
status?: ArtifactVersionStatus | 'all' | null;
|
|
164
|
+
};
|
|
165
|
+
export type EnsureArtifactVersionResult = {
|
|
166
|
+
version: ArtifactVersionRecord;
|
|
167
|
+
outcome: 'created' | 'reused';
|
|
168
|
+
};
|
|
169
|
+
export type ArtifactShareKeyInput = {
|
|
170
|
+
artifactId: string;
|
|
171
|
+
shareKey: string;
|
|
172
|
+
};
|
|
173
|
+
export type EnsureArtifactShareResult = {
|
|
174
|
+
link: ArtifactLinkRecord;
|
|
175
|
+
outcome: 'created' | 'reused' | 'replaced';
|
|
176
|
+
replacedLinkId?: string | null;
|
|
177
|
+
};
|
|
143
178
|
/** Mutable parts of an Artifact link; content versions remain immutable. */
|
|
144
179
|
export type UpdateArtifactLinkAccessInput = {
|
|
145
180
|
access?: ArtifactLinkAccessInput | null;
|
|
@@ -150,12 +185,18 @@ export type UpdateArtifactLinkAccessInput = {
|
|
|
150
185
|
/** Platform runtime capability exposed to plugins for managing generated Artifacts. */
|
|
151
186
|
export interface ArtifactsApi {
|
|
152
187
|
createArtifact(input: CreateArtifactInput): Promise<ArtifactRecord>;
|
|
188
|
+
findArtifactBySource(input: FindArtifactBySourceInput): Promise<ArtifactRecord | null>;
|
|
153
189
|
createArtifactVersion(input: CreateArtifactVersionInput): Promise<ArtifactVersionRecord>;
|
|
190
|
+
listArtifactVersions(input: ListArtifactVersionsInput): Promise<ArtifactVersionRecord[]>;
|
|
191
|
+
ensureArtifactVersion(input: EnsureArtifactVersionInput): Promise<EnsureArtifactVersionResult>;
|
|
154
192
|
getArtifact(idOrSlug: string): Promise<ArtifactRecord>;
|
|
155
193
|
listArtifacts(input?: ListArtifactsInput): Promise<ListArtifactsResult>;
|
|
156
194
|
archiveArtifact(idOrSlug: string): Promise<ArtifactRecord>;
|
|
157
195
|
deleteArtifact(idOrSlug: string): Promise<ArtifactRecord>;
|
|
158
196
|
createArtifactLink(input: CreateArtifactLinkInput): Promise<ArtifactLinkRecord>;
|
|
197
|
+
getArtifactShare(input: ArtifactShareKeyInput): Promise<ArtifactLinkRecord | null>;
|
|
198
|
+
ensureArtifactShare(input: ArtifactShareInput): Promise<EnsureArtifactShareResult>;
|
|
199
|
+
revokeArtifactShare(input: ArtifactShareKeyInput): Promise<ArtifactLinkRecord | null>;
|
|
159
200
|
createSignedPreviewLink(input: CreateSignedArtifactPreviewLinkInput): Promise<ArtifactLinkRecord>;
|
|
160
201
|
updateArtifactLinkAccess(idOrSlug: string, patch: UpdateArtifactLinkAccessInput): Promise<ArtifactLinkRecord>;
|
|
161
202
|
revokeArtifactLink(idOrSlug: string): Promise<ArtifactLinkRecord>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { JSONValue } from '@xpert-ai/contracts';
|
|
2
|
+
import type { WorkspaceFileScope, WorkspacePortableFileReference } from './workspace-files';
|
|
3
|
+
/** Stable machine-readable failures emitted by the Sandbox Jobs capability. */
|
|
4
|
+
export declare const SANDBOX_JOB_ERROR_CODES: readonly ["SANDBOX_ACTION_UNAVAILABLE", "SANDBOX_ACTION_INVALID", "SANDBOX_PROFILE_UNAVAILABLE", "SANDBOX_RUNTIME_UNAVAILABLE", "SANDBOX_VERSION_MISMATCH", "SANDBOX_CAPACITY_UNAVAILABLE", "SANDBOX_START_FAILED", "BROWSER_LAUNCH_FAILED", "EXPORT_TIMEOUT", "EXPORT_OOM", "EXPORT_INPUT_INVALID", "EXPORT_OUTPUT_INVALID", "SANDBOX_CANCELLED"];
|
|
5
|
+
export type SandboxJobErrorCode = (typeof SANDBOX_JOB_ERROR_CODES)[number];
|
|
6
|
+
/** Persisted lifecycle states for a generic isolated background execution. */
|
|
7
|
+
export type SandboxJobStatus = 'waiting' | 'starting' | 'running' | 'succeeded' | 'failed' | 'cancelled' | 'lost';
|
|
8
|
+
/** Portable Workspace Files input materialized under `/workspace/input`. */
|
|
9
|
+
export type SandboxJobFileInput = {
|
|
10
|
+
/** Tenant-scoped portable reference; raw bytes never enter queue state. */
|
|
11
|
+
reference: WorkspacePortableFileReference;
|
|
12
|
+
/** Safe relative path below `/workspace/input`. */
|
|
13
|
+
targetPath: string;
|
|
14
|
+
/** Expected immutable byte length checked during materialization. */
|
|
15
|
+
size: number;
|
|
16
|
+
/** Expected lowercase SHA-256 checked during materialization. */
|
|
17
|
+
sha256: string;
|
|
18
|
+
};
|
|
19
|
+
/** Declares one output to validate and persist back into Workspace Files. */
|
|
20
|
+
export type SandboxJobOutputRequest = {
|
|
21
|
+
path: string;
|
|
22
|
+
originalName: string;
|
|
23
|
+
mimeType: string;
|
|
24
|
+
destination: WorkspaceFileScope & {
|
|
25
|
+
folder: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/** Tenant and business ownership recorded for authorization, audit, and cleanup. */
|
|
29
|
+
export type SandboxJobScope = {
|
|
30
|
+
tenantId: string;
|
|
31
|
+
organizationId?: string | null;
|
|
32
|
+
userId?: string | null;
|
|
33
|
+
pluginName: string;
|
|
34
|
+
businessResourceType: string;
|
|
35
|
+
businessResourceId: string;
|
|
36
|
+
};
|
|
37
|
+
/** Action-oriented request accepted from a plugin background handler. */
|
|
38
|
+
export type SandboxJobRunInput = {
|
|
39
|
+
/** Optional caller-known UUID used when cancellation must be possible while run() is awaiting completion. */
|
|
40
|
+
jobId?: string;
|
|
41
|
+
action: string;
|
|
42
|
+
actionVersion: string;
|
|
43
|
+
/** Stable tenant-scoped key combining business identity and immutable input checksum. */
|
|
44
|
+
idempotencyKey: string;
|
|
45
|
+
scope: SandboxJobScope;
|
|
46
|
+
/** Small structured request; file bytes must be supplied through `files`. */
|
|
47
|
+
payload: JSONValue;
|
|
48
|
+
files?: SandboxJobFileInput[];
|
|
49
|
+
outputs: SandboxJobOutputRequest[];
|
|
50
|
+
/** Soft execution limit capped by the Runtime Definition's hard deadline. */
|
|
51
|
+
timeoutMs?: number;
|
|
52
|
+
};
|
|
53
|
+
/** Validated output evidence returned as a portable Workspace Files reference. */
|
|
54
|
+
export type SandboxJobOutput = {
|
|
55
|
+
path: string;
|
|
56
|
+
originalName: string;
|
|
57
|
+
mimeType: string;
|
|
58
|
+
size: number;
|
|
59
|
+
sha256: string;
|
|
60
|
+
reference: WorkspacePortableFileReference;
|
|
61
|
+
fileUrl?: string;
|
|
62
|
+
workspacePath?: string;
|
|
63
|
+
};
|
|
64
|
+
/** Provider-neutral persisted view of a Sandbox Job and its runtime evidence. */
|
|
65
|
+
export type SandboxJobSnapshot = {
|
|
66
|
+
id: string;
|
|
67
|
+
runtimeProfile: string;
|
|
68
|
+
sandboxRuntimeVersion: string;
|
|
69
|
+
action: string;
|
|
70
|
+
actionVersion: string;
|
|
71
|
+
status: SandboxJobStatus;
|
|
72
|
+
/** Attempt number; a new failed-job attempt may select a newly healthy Binding. */
|
|
73
|
+
attempt: number;
|
|
74
|
+
/** Provider and Binding are persisted so cleanup never depends on current selection. */
|
|
75
|
+
provider?: string | null;
|
|
76
|
+
runtimeBindingId?: string | null;
|
|
77
|
+
/** Opaque Provider identity used for reattachment and idempotent destruction. */
|
|
78
|
+
runtimeRef?: string | null;
|
|
79
|
+
artifactDigest?: string | null;
|
|
80
|
+
/** @deprecated Use runtimeRef. Kept for one compatibility cycle. */
|
|
81
|
+
containerRef?: string | null;
|
|
82
|
+
outputs: SandboxJobOutput[];
|
|
83
|
+
errorCode?: SandboxJobErrorCode | null;
|
|
84
|
+
errorMessage?: string | null;
|
|
85
|
+
createdAt?: Date | string | null;
|
|
86
|
+
startedAt?: Date | string | null;
|
|
87
|
+
finishedAt?: Date | string | null;
|
|
88
|
+
};
|
|
89
|
+
/** Successful `run()` result; failed executions reject with SandboxJobRuntimeError. */
|
|
90
|
+
export type SandboxJobRunResult = SandboxJobSnapshot & {
|
|
91
|
+
status: 'succeeded';
|
|
92
|
+
};
|
|
93
|
+
/** Aggregated readiness of an Action, Runtime Definition, Worker, Binding, and Provider. */
|
|
94
|
+
export type SandboxJobActionHealth = {
|
|
95
|
+
pluginName: string;
|
|
96
|
+
action: string;
|
|
97
|
+
actionVersion: string;
|
|
98
|
+
runtimeProfile?: string;
|
|
99
|
+
sandboxRuntimeVersion?: string;
|
|
100
|
+
provider?: string;
|
|
101
|
+
runtimeBindingId?: string;
|
|
102
|
+
artifactDigest?: string;
|
|
103
|
+
available: boolean;
|
|
104
|
+
reason?: 'ACTION_MISSING' | 'ACTION_INVALID' | 'PROFILE_MISSING' | 'VERSION_MISMATCH' | 'RUNTIME_UNBOUND' | 'PROVIDER_UNAVAILABLE' | 'PROFILE_UNHEALTHY';
|
|
105
|
+
message?: string;
|
|
106
|
+
manifest?: Record<string, string>;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Plugin-facing API for registered, structured Sandbox Actions.
|
|
110
|
+
*
|
|
111
|
+
* Callers choose only an Action and its version; images, commands, entrypoints,
|
|
112
|
+
* environment variables, and Provider options are resolved and enforced by Core.
|
|
113
|
+
*/
|
|
114
|
+
export interface SandboxJobsApi {
|
|
115
|
+
/** Starts, reattaches, or reuses a successful execution by tenant-scoped idempotency key. */
|
|
116
|
+
run(input: SandboxJobRunInput): Promise<SandboxJobRunResult>;
|
|
117
|
+
/** Cancels the logical Job and terminates its active Runtime when one exists. */
|
|
118
|
+
cancel(input: {
|
|
119
|
+
jobId: string;
|
|
120
|
+
}): Promise<SandboxJobSnapshot>;
|
|
121
|
+
/** Returns the active tenant's persisted Job snapshot, or null when inaccessible or absent. */
|
|
122
|
+
getJob(input: {
|
|
123
|
+
jobId: string;
|
|
124
|
+
}): Promise<SandboxJobSnapshot | null>;
|
|
125
|
+
/** Checks readiness before a product exposes or enqueues a browser-backed operation. */
|
|
126
|
+
getActionHealth(input: {
|
|
127
|
+
pluginName: string;
|
|
128
|
+
action: string;
|
|
129
|
+
actionVersion: string;
|
|
130
|
+
}): Promise<SandboxJobActionHealth>;
|
|
131
|
+
}
|
|
132
|
+
/** Error carrying retry policy and Job identity across plugin queue handlers. */
|
|
133
|
+
export declare class SandboxJobRuntimeError extends Error {
|
|
134
|
+
readonly code: SandboxJobErrorCode;
|
|
135
|
+
readonly retryable: boolean;
|
|
136
|
+
readonly jobId?: string;
|
|
137
|
+
constructor(code: SandboxJobErrorCode, message: string, retryable: boolean, jobId?: string);
|
|
138
|
+
}
|
|
139
|
+
/** Narrows an unknown failure to the structured Sandbox Jobs runtime error contract. */
|
|
140
|
+
export declare function isSandboxJobRuntimeError(error: unknown): error is SandboxJobRuntimeError;
|
|
141
|
+
/** Runtime capability key used to resolve SandboxJobsApi from the platform registry. */
|
|
142
|
+
export declare const SandboxJobsRuntimeCapability: import("../../core/runtime-capability").RuntimeCapabilityKey<SandboxJobsApi>;
|
|
@@ -6,6 +6,12 @@ export * from './sandbox.decorator';
|
|
|
6
6
|
export * from './sandbox.interface';
|
|
7
7
|
export * from './sandbox.registry';
|
|
8
8
|
export * from './terminal';
|
|
9
|
+
export * from './runtime-provider';
|
|
10
|
+
export * from './runtime-provider.decorator';
|
|
11
|
+
export * from './runtime-provider.registry';
|
|
12
|
+
export * from './workspace-mapper';
|
|
13
|
+
export * from './workspace-mapper.decorator';
|
|
14
|
+
export * from './workspace-mapper.registry';
|
|
9
15
|
export * from './sandbox.interface';
|
|
10
16
|
export * from './sandbox.decorator';
|
|
11
17
|
export * from './sandbox.registry';
|
|
@@ -155,6 +155,8 @@ export interface ExecuteResponse {
|
|
|
155
155
|
truncated: boolean;
|
|
156
156
|
/** Whether the command exceeded its timeout and was terminated */
|
|
157
157
|
timedOut?: boolean;
|
|
158
|
+
/** Provider-observed container/process termination reason. */
|
|
159
|
+
terminationReason?: 'oom' | 'deadline' | 'cancelled' | 'container-died';
|
|
158
160
|
}
|
|
159
161
|
/**
|
|
160
162
|
* Standardized error codes for file upload/download operations.
|
|
@@ -346,6 +348,8 @@ export interface SandboxBackendProtocol extends BackendProtocol {
|
|
|
346
348
|
readonly id: string;
|
|
347
349
|
/** Canonical sandbox environment identifier bound to this backend */
|
|
348
350
|
readonly environmentId?: string | null;
|
|
351
|
+
/** Best-effort immediate termination for an ephemeral job sandbox. */
|
|
352
|
+
terminate?(): MaybePromise<void>;
|
|
349
353
|
}
|
|
350
354
|
export declare function isSandboxBackend(backend: unknown): backend is SandboxBackendProtocol;
|
|
351
355
|
export declare function resolveSandboxBackend(sandbox: TSandboxConfigurable | SandboxBackendProtocol | null | undefined | unknown): SandboxBackendProtocol | null;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/** Per-execution limits applied to the Runtime Definition's fixed Runner command. */
|
|
2
|
+
export type SandboxRuntimeExecutionOptions = {
|
|
3
|
+
timeoutMs?: number;
|
|
4
|
+
maxOutputBytes?: number;
|
|
5
|
+
};
|
|
6
|
+
/** Provider-observed reason why a Runtime execution stopped without a normal exit. */
|
|
7
|
+
export type SandboxRuntimeTerminationReason = 'oom' | 'deadline' | 'cancelled' | 'runtime-died';
|
|
8
|
+
/** Normalized process result returned by every Sandbox Runtime implementation. */
|
|
9
|
+
export type SandboxRuntimeExecuteResponse = {
|
|
10
|
+
output: string;
|
|
11
|
+
exitCode: number | null;
|
|
12
|
+
truncated: boolean;
|
|
13
|
+
timedOut?: boolean;
|
|
14
|
+
terminationReason?: SandboxRuntimeTerminationReason;
|
|
15
|
+
};
|
|
16
|
+
/** Portable failure categories for Runtime workspace file operations. */
|
|
17
|
+
export type SandboxRuntimeFileOperationError = 'file_not_found' | 'permission_denied' | 'is_directory' | 'invalid_path';
|
|
18
|
+
export type SandboxRuntimeFileUploadResponse = {
|
|
19
|
+
path: string;
|
|
20
|
+
error: SandboxRuntimeFileOperationError | null;
|
|
21
|
+
};
|
|
22
|
+
export type SandboxRuntimeFileDownloadResponse = {
|
|
23
|
+
path: string;
|
|
24
|
+
content: Uint8Array | null;
|
|
25
|
+
error: SandboxRuntimeFileOperationError | null;
|
|
26
|
+
};
|
|
27
|
+
/** Resource policy requested by a provider-neutral Runtime Definition. */
|
|
28
|
+
export type SandboxRuntimeResources = {
|
|
29
|
+
memoryMb: number;
|
|
30
|
+
cpu: number;
|
|
31
|
+
shmSizeMb: number;
|
|
32
|
+
tempDiskMb: number;
|
|
33
|
+
};
|
|
34
|
+
/** Network access that a Provider must enforce for the Runtime instance. */
|
|
35
|
+
export type SandboxRuntimeNetworkPolicy = {
|
|
36
|
+
mode: 'none' | 'internal-only';
|
|
37
|
+
allowedHosts?: string[];
|
|
38
|
+
};
|
|
39
|
+
/** Mandatory process and filesystem hardening for a Runtime instance. */
|
|
40
|
+
export type SandboxRuntimeSecurity = {
|
|
41
|
+
runAsNonRoot: boolean;
|
|
42
|
+
readOnlyRootFilesystem: boolean;
|
|
43
|
+
noNewPrivileges: boolean;
|
|
44
|
+
dropCapabilities: 'all';
|
|
45
|
+
};
|
|
46
|
+
/** Isolation guarantees a Provider advertises before it can be selected. */
|
|
47
|
+
export type SandboxRuntimeProviderCapabilities = {
|
|
48
|
+
isolation: 'process' | 'hardened';
|
|
49
|
+
ephemeral: boolean;
|
|
50
|
+
resourceLimits: boolean;
|
|
51
|
+
networkPolicy: boolean;
|
|
52
|
+
readOnlyRootFilesystem: boolean;
|
|
53
|
+
};
|
|
54
|
+
/** Minimum Provider guarantees required by a Runtime Definition. */
|
|
55
|
+
export type SandboxRuntimeRequirements = SandboxRuntimeProviderCapabilities;
|
|
56
|
+
/**
|
|
57
|
+
* Provider-neutral execution profile published by the Sandbox Runtime Suite.
|
|
58
|
+
*
|
|
59
|
+
* Definitions select no image, engine, plugin, or host path. The platform owns
|
|
60
|
+
* the fixed Runner command and matches it to a compatible Provider Binding.
|
|
61
|
+
*/
|
|
62
|
+
export type SandboxRuntimeDefinition = {
|
|
63
|
+
/** Stable profile identity referenced by Action manifests. */
|
|
64
|
+
name: string;
|
|
65
|
+
/** Trusted Runner Host argv. Plugin callers cannot override this value. */
|
|
66
|
+
command: readonly string[];
|
|
67
|
+
/** Runner Host protocol version shared with compatible Action Bundles. */
|
|
68
|
+
contractVersion: string;
|
|
69
|
+
/** Version of the Runtime Suite contents, independent of Provider version. */
|
|
70
|
+
sandboxRuntimeVersion: string;
|
|
71
|
+
timeoutMs: number;
|
|
72
|
+
hardDeadlineMs: number;
|
|
73
|
+
resources: SandboxRuntimeResources;
|
|
74
|
+
networkPolicy: SandboxRuntimeNetworkPolicy;
|
|
75
|
+
security: SandboxRuntimeSecurity;
|
|
76
|
+
requirements: SandboxRuntimeRequirements;
|
|
77
|
+
expectedManifest: Record<string, string>;
|
|
78
|
+
};
|
|
79
|
+
/** Immutable or provider-addressable runtime artifact selected by a Binding. */
|
|
80
|
+
export type SandboxRuntimeArtifact = {
|
|
81
|
+
kind: 'oci-image' | 'filesystem' | 'remote-runtime';
|
|
82
|
+
/** Provider-native immutable address; OCI production references must include a digest. */
|
|
83
|
+
reference: string;
|
|
84
|
+
/** Normalized digest retained separately as runtime evidence when available. */
|
|
85
|
+
digest?: string;
|
|
86
|
+
};
|
|
87
|
+
/** Provider-owned mapping from one Runtime Definition to an executable artifact. */
|
|
88
|
+
export type SandboxRuntimeBinding = {
|
|
89
|
+
/** Stable Provider-owned Binding identity persisted on every attempt. */
|
|
90
|
+
id: string;
|
|
91
|
+
runtimeProfile: string;
|
|
92
|
+
/** Must match the registered Provider strategy type. */
|
|
93
|
+
provider: string;
|
|
94
|
+
/** Lower values are preferred. Ties are resolved by provider and binding id. */
|
|
95
|
+
priority: number;
|
|
96
|
+
providerVersion: string;
|
|
97
|
+
artifact: SandboxRuntimeArtifact;
|
|
98
|
+
};
|
|
99
|
+
/** Result of verifying an engine, artifact, security guarantees, and Runtime manifest. */
|
|
100
|
+
export type SandboxRuntimeBindingHealth = {
|
|
101
|
+
available: boolean;
|
|
102
|
+
reason?: string;
|
|
103
|
+
manifest?: Record<string, string>;
|
|
104
|
+
};
|
|
105
|
+
/** Job-isolated storage roots passed to a Provider without exposing them to plugins. */
|
|
106
|
+
export type SandboxRuntimeVolume = {
|
|
107
|
+
/** Path visible to the Xpert process. */
|
|
108
|
+
serverRoot: string;
|
|
109
|
+
/** Path suitable for a provider-side bind mount. */
|
|
110
|
+
hostRoot: string;
|
|
111
|
+
};
|
|
112
|
+
/** Fully resolved policy used to create or reattach one ephemeral Job Runtime. */
|
|
113
|
+
export type SandboxRuntimeCreateOptions = {
|
|
114
|
+
tenantId: string;
|
|
115
|
+
workFor: {
|
|
116
|
+
type: 'job';
|
|
117
|
+
id: string;
|
|
118
|
+
};
|
|
119
|
+
definition: SandboxRuntimeDefinition;
|
|
120
|
+
binding: SandboxRuntimeBinding;
|
|
121
|
+
volume: SandboxRuntimeVolume;
|
|
122
|
+
ephemeral: true;
|
|
123
|
+
resources: SandboxRuntimeResources;
|
|
124
|
+
networkPolicy: SandboxRuntimeNetworkPolicy;
|
|
125
|
+
security: SandboxRuntimeSecurity;
|
|
126
|
+
hardDeadlineMs: number;
|
|
127
|
+
};
|
|
128
|
+
/** Persisted evidence required to destroy a Runtime even after Provider reload. */
|
|
129
|
+
export type SandboxRuntimeDestroyOptions = {
|
|
130
|
+
tenantId: string;
|
|
131
|
+
workFor: {
|
|
132
|
+
type: 'job';
|
|
133
|
+
id: string;
|
|
134
|
+
};
|
|
135
|
+
runtimeProfile: string;
|
|
136
|
+
runtimeBindingId: string;
|
|
137
|
+
artifact: SandboxRuntimeArtifact;
|
|
138
|
+
runtimeRef?: string | null;
|
|
139
|
+
};
|
|
140
|
+
/**
|
|
141
|
+
* Minimal execution surface required by Sandbox Jobs.
|
|
142
|
+
*
|
|
143
|
+
* Implementations must constrain `execute()` to the Definition's trusted Runner
|
|
144
|
+
* argv and must confine all file operations to `workspaceRoot`.
|
|
145
|
+
*/
|
|
146
|
+
export interface SandboxRuntimeInstance {
|
|
147
|
+
readonly id: string;
|
|
148
|
+
/** Absolute path visible inside the isolated Runtime, normally `/workspace`. */
|
|
149
|
+
readonly workspaceRoot: string;
|
|
150
|
+
/** Executes Core-supplied argv after the Provider verifies the trusted Runner prefix. */
|
|
151
|
+
execute(argv: readonly string[], options?: SandboxRuntimeExecutionOptions): Promise<SandboxRuntimeExecuteResponse>;
|
|
152
|
+
/** Writes files only inside the instance workspace and returns per-path failures. */
|
|
153
|
+
uploadFiles(files: Array<[string, Uint8Array]>): Promise<SandboxRuntimeFileUploadResponse[]>;
|
|
154
|
+
/** Reads files only inside the instance workspace and returns per-path failures. */
|
|
155
|
+
downloadFiles(paths: string[]): Promise<SandboxRuntimeFileDownloadResponse[]>;
|
|
156
|
+
/** Best-effort immediate termination used by cancellation and deadline handling. */
|
|
157
|
+
terminate?(): Promise<void> | void;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Small Provider SPI for background Sandbox Jobs.
|
|
161
|
+
*
|
|
162
|
+
* This interface is intentionally independent from the interactive Agent Sandbox
|
|
163
|
+
* backend protocol. Providers are registered only by built-ins or system plugins,
|
|
164
|
+
* are selected from declared Bindings, and must make `destroy()` idempotent.
|
|
165
|
+
*/
|
|
166
|
+
export interface ISandboxRuntimeProvider {
|
|
167
|
+
readonly type: string;
|
|
168
|
+
readonly version: string;
|
|
169
|
+
readonly capabilities: SandboxRuntimeProviderCapabilities;
|
|
170
|
+
/** Lists immutable artifacts this Provider can bind to Runtime Definitions. */
|
|
171
|
+
listBindings(): Promise<readonly SandboxRuntimeBinding[]> | readonly SandboxRuntimeBinding[];
|
|
172
|
+
/** Probes the engine and artifact without creating a business Job instance. */
|
|
173
|
+
getBindingHealth(input: {
|
|
174
|
+
definition: SandboxRuntimeDefinition;
|
|
175
|
+
binding: SandboxRuntimeBinding;
|
|
176
|
+
}): Promise<SandboxRuntimeBindingHealth>;
|
|
177
|
+
/** Creates or reattaches the unique Runtime instance for the supplied Job scope. */
|
|
178
|
+
create(options: SandboxRuntimeCreateOptions): Promise<SandboxRuntimeInstance>;
|
|
179
|
+
/** Idempotently reclaims a Runtime by persisted scope, Binding, and runtimeRef evidence. */
|
|
180
|
+
destroy(options: SandboxRuntimeDestroyOptions): Promise<void>;
|
|
181
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const SANDBOX_RUNTIME_PROVIDER = "SANDBOX_RUNTIME_PROVIDER";
|
|
2
|
+
/** Marks a built-in or system-plugin class as a named Sandbox Runtime Provider strategy. */
|
|
3
|
+
export declare const SandboxRuntimeProviderStrategy: (provider: string) => <TFunction extends Function, Y>(target: TFunction | object, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DiscoveryService, Reflector } from '@nestjs/core';
|
|
2
|
+
import { BaseStrategyRegistry } from '../strategy';
|
|
3
|
+
import type { ISandboxRuntimeProvider } from './runtime-provider';
|
|
4
|
+
/** Discovers Runtime Provider strategies and rejects organization-scoped executable infrastructure. */
|
|
5
|
+
export declare class SandboxRuntimeProviderRegistry extends BaseStrategyRegistry<ISandboxRuntimeProvider> {
|
|
6
|
+
private readonly runtimeLogger;
|
|
7
|
+
constructor(discoveryService: DiscoveryService, reflector: Reflector);
|
|
8
|
+
upsert(instance: unknown): void;
|
|
9
|
+
}
|
|
@@ -39,6 +39,30 @@ export type SandboxProviderCreateOptions = {
|
|
|
39
39
|
* Tenant identifier
|
|
40
40
|
*/
|
|
41
41
|
tenantId?: string;
|
|
42
|
+
/** Registered runtime profile. Providers resolve this to an immutable image. */
|
|
43
|
+
profile?: string;
|
|
44
|
+
/** Immutable image reference selected by the profile registry. */
|
|
45
|
+
image?: string;
|
|
46
|
+
/** Job sandboxes are never reused after the action completes. */
|
|
47
|
+
ephemeral?: boolean;
|
|
48
|
+
resources?: {
|
|
49
|
+
memoryMb?: number;
|
|
50
|
+
cpu?: number;
|
|
51
|
+
shmSizeMb?: number;
|
|
52
|
+
tempDiskMb?: number;
|
|
53
|
+
};
|
|
54
|
+
networkPolicy?: {
|
|
55
|
+
mode: 'none' | 'internal-only';
|
|
56
|
+
allowedHosts?: string[];
|
|
57
|
+
};
|
|
58
|
+
security?: {
|
|
59
|
+
runAsNonRoot: boolean;
|
|
60
|
+
readOnlyRootFilesystem: boolean;
|
|
61
|
+
noNewPrivileges: boolean;
|
|
62
|
+
dropCapabilities: 'all';
|
|
63
|
+
};
|
|
64
|
+
/** Provider-enforced absolute lifetime for the sandbox. */
|
|
65
|
+
hardDeadlineMs?: number;
|
|
42
66
|
workFor: {
|
|
43
67
|
type: TSandboxWorkForType;
|
|
44
68
|
id: string;
|
|
@@ -53,6 +77,22 @@ export interface ISandboxProvider<T extends SandboxBackendProtocol = SandboxBack
|
|
|
53
77
|
* @param options
|
|
54
78
|
*/
|
|
55
79
|
create(options?: SandboxProviderCreateOptions): Promise<T>;
|
|
80
|
+
/** Destroy an ephemeral sandbox by its stable work identity after process loss or cancellation. */
|
|
81
|
+
destroy?(options: SandboxProviderCreateOptions & {
|
|
82
|
+
containerRef?: string | null;
|
|
83
|
+
}): Promise<void>;
|
|
84
|
+
/** Provider-side image/runner readiness check used by profile health. */
|
|
85
|
+
getProfileHealth?(input: {
|
|
86
|
+
profile: string;
|
|
87
|
+
image?: string;
|
|
88
|
+
/** Exact trusted command used to read the runner manifest. */
|
|
89
|
+
manifestCommand?: readonly string[];
|
|
90
|
+
expectedManifest?: Record<string, string>;
|
|
91
|
+
}): Promise<{
|
|
92
|
+
available: boolean;
|
|
93
|
+
reason?: string;
|
|
94
|
+
manifest?: Record<string, string>;
|
|
95
|
+
}>;
|
|
56
96
|
/**
|
|
57
97
|
* Get default working directory for the sandbox instances
|
|
58
98
|
*/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SandboxWorkspaceBinding } from './sandbox.interface';
|
|
2
|
+
/** Server-visible and Provider-visible roots for the same isolated volume. */
|
|
3
|
+
export type SandboxWorkspaceVolume = {
|
|
4
|
+
serverRoot: string;
|
|
5
|
+
hostRoot: string;
|
|
6
|
+
};
|
|
7
|
+
/** Optional server path to translate within a mapped volume. */
|
|
8
|
+
export type SandboxWorkspaceMappingOptions = {
|
|
9
|
+
serverPath?: string;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Translates paths between platform volumes and Provider-visible workspaces.
|
|
13
|
+
* Engine-specific path logic belongs here instead of in OSS Volume services.
|
|
14
|
+
*/
|
|
15
|
+
export interface SandboxWorkspaceMapper {
|
|
16
|
+
/** Produces a Provider-visible binding for one path inside the isolated platform volume. */
|
|
17
|
+
mapVolumeToWorkspace(volume: SandboxWorkspaceVolume, options?: SandboxWorkspaceMappingOptions): SandboxWorkspaceBinding;
|
|
18
|
+
/** Converts a Provider-visible path back to its server path, rejecting escapes. */
|
|
19
|
+
mapWorkspaceToVolume(binding: SandboxWorkspaceBinding, workspacePath: string): string;
|
|
20
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const SANDBOX_WORKSPACE_MAPPER = "SANDBOX_WORKSPACE_MAPPER";
|
|
2
|
+
/** Associates a workspace path mapper with a named Runtime Provider strategy. */
|
|
3
|
+
export declare const SandboxWorkspaceMapperStrategy: (provider: string) => <TFunction extends Function, Y>(target: TFunction | object, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DiscoveryService, Reflector } from '@nestjs/core';
|
|
2
|
+
import { BaseStrategyRegistry } from '../strategy';
|
|
3
|
+
import type { SandboxWorkspaceMapper } from './workspace-mapper';
|
|
4
|
+
/** Discovers Provider path mappers while enforcing the same system-level trust boundary as Providers. */
|
|
5
|
+
export declare class SandboxWorkspaceMapperRegistry extends BaseStrategyRegistry<SandboxWorkspaceMapper> {
|
|
6
|
+
private readonly mapperLogger;
|
|
7
|
+
constructor(discoveryService: DiscoveryService, reflector: Reflector);
|
|
8
|
+
upsert(instance: unknown): void;
|
|
9
|
+
}
|
package/src/lib/strategy.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OnModuleInit } from '@nestjs/common';
|
|
1
|
+
import { OnModuleInit, type Type } from '@nestjs/common';
|
|
2
2
|
import { DiscoveryService, Reflector } from '@nestjs/core';
|
|
3
3
|
import { StrategyBus } from './core/strategy-bus';
|
|
4
4
|
export declare class BaseStrategyRegistry<S> implements OnModuleInit {
|
|
@@ -11,7 +11,7 @@ export declare class BaseStrategyRegistry<S> implements OnModuleInit {
|
|
|
11
11
|
protected pluginStrategies: Map<string, Set<string>>;
|
|
12
12
|
constructor(strategyKey: string, discoveryService: DiscoveryService, reflector: Reflector);
|
|
13
13
|
onModuleInit(): void;
|
|
14
|
-
upsert(instance:
|
|
14
|
+
upsert(instance: unknown): void;
|
|
15
15
|
/**
|
|
16
16
|
* Remove all strategies registered by the given plugin for the given scope.
|
|
17
17
|
*/
|
|
@@ -38,3 +38,7 @@ export declare class BaseStrategyRegistry<S> implements OnModuleInit {
|
|
|
38
38
|
*/
|
|
39
39
|
list(organizationId?: string): S[];
|
|
40
40
|
}
|
|
41
|
+
/** Returns whether a discovered provider can carry decorator metadata. */
|
|
42
|
+
export declare function isStrategyInstance(instance: unknown): instance is object;
|
|
43
|
+
/** Resolves the class used for plugin and organization metadata without reflecting over primitive provider values. */
|
|
44
|
+
export declare function resolveStrategyMetadataTarget(instance: unknown): Type<unknown> | null;
|