antpath 0.9.2 → 0.10.7
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/_shared/blueprint.d.ts +70 -2
- package/dist/_shared/blueprint.js +38 -3
- package/dist/_shared/operations.d.ts +85 -10
- package/dist/_shared/operations.js +148 -12
- package/dist/_shared/run-unit.js +4 -0
- package/dist/_shared/runtime-types.d.ts +47 -0
- package/dist/_shared/submission.d.ts +3 -1
- package/dist/_shared/submission.js +103 -0
- package/dist/agents-md.d.ts +90 -0
- package/dist/agents-md.js +171 -0
- package/dist/agents-md.js.map +1 -0
- package/dist/asset-upload.d.ts +85 -0
- package/dist/asset-upload.js +124 -0
- package/dist/asset-upload.js.map +1 -0
- package/dist/bundle.js +3 -1
- package/dist/bundle.js.map +1 -1
- package/dist/cli.mjs +114 -4
- package/dist/cli.mjs.sha256 +1 -1
- package/dist/client.d.ts +98 -5
- package/dist/client.js +207 -19
- package/dist/client.js.map +1 -1
- package/dist/file.d.ts +117 -0
- package/dist/file.js +287 -0
- package/dist/file.js.map +1 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/skill.d.ts +29 -0
- package/dist/skill.js +38 -1
- package/dist/skill.js.map +1 -1
- package/docs/skills.md +76 -24
- package/package.json +3 -2
|
@@ -135,6 +135,55 @@ export declare const TRANSIENT_CONTENT_HASH_PATTERN: RegExp;
|
|
|
135
135
|
export declare function isWorkspaceSkillRef(ref: SkillRef): ref is WorkspaceSkillRef;
|
|
136
136
|
export declare function isProviderSkillRef(ref: SkillRef): ref is ProviderSkillRef;
|
|
137
137
|
export declare function isTransientSkillRef(ref: SkillRef): ref is TransientSkillRef;
|
|
138
|
+
export type AgentsMdRef = WorkspaceAgentsMdRef | TransientAgentsMdRef;
|
|
139
|
+
export interface WorkspaceAgentsMdRef {
|
|
140
|
+
readonly kind: "workspace_agentsmd";
|
|
141
|
+
readonly id: string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Inline-supplied AgentsMd content that arrives as the
|
|
145
|
+
* `agentsmd:<slot>` part of a multipart `submitRun` body. The BFF
|
|
146
|
+
* ingests the bytes into `workspace_files` (kind='agentsmd') at
|
|
147
|
+
* submission time and rewrites the ref to `WorkspaceAgentsMdRef`
|
|
148
|
+
* before the rest of the run-submission pipeline runs.
|
|
149
|
+
*
|
|
150
|
+
* `name` becomes the prefix of the auto-suffixed workspace name,
|
|
151
|
+
* mirroring the `Skill` per-run-artifact model. `contentHash` is
|
|
152
|
+
* the SDK's advisory `sha256:<hex>` for tamper detection.
|
|
153
|
+
*/
|
|
154
|
+
export interface TransientAgentsMdRef {
|
|
155
|
+
readonly kind: "transient_agentsmd";
|
|
156
|
+
readonly slot: string;
|
|
157
|
+
readonly name: string;
|
|
158
|
+
readonly contentHash: string;
|
|
159
|
+
}
|
|
160
|
+
export declare function isWorkspaceAgentsMdRef(ref: AgentsMdRef): ref is WorkspaceAgentsMdRef;
|
|
161
|
+
export declare function isTransientAgentsMdRef(ref: AgentsMdRef): ref is TransientAgentsMdRef;
|
|
162
|
+
export type FileRef = WorkspaceFileRef | TransientFileRef;
|
|
163
|
+
export interface WorkspaceFileRef {
|
|
164
|
+
readonly kind: "workspace_file";
|
|
165
|
+
readonly id: string;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Inline-supplied File content that arrives as the `file:<slot>`
|
|
169
|
+
* part of a multipart `submitRun` body. Single file or a zipped
|
|
170
|
+
* folder. The BFF ingests and rewrites the ref to
|
|
171
|
+
* `WorkspaceFileRef` before run submission proceeds.
|
|
172
|
+
*
|
|
173
|
+
* `name` is the workspace-visible name prefix. `contentHash` is the
|
|
174
|
+
* SDK's advisory `sha256:<hex>`. `mountPath` is optional — when
|
|
175
|
+
* present it overrides the default `/antpath/files/<id>/<rel>` mount
|
|
176
|
+
* layout (e.g. user-chosen `/workspace/data`).
|
|
177
|
+
*/
|
|
178
|
+
export interface TransientFileRef {
|
|
179
|
+
readonly kind: "transient_file";
|
|
180
|
+
readonly slot: string;
|
|
181
|
+
readonly name: string;
|
|
182
|
+
readonly contentHash: string;
|
|
183
|
+
readonly mountPath?: string;
|
|
184
|
+
}
|
|
185
|
+
export declare function isWorkspaceFileRef(ref: FileRef): ref is WorkspaceFileRef;
|
|
186
|
+
export declare function isTransientFileRef(ref: FileRef): ref is TransientFileRef;
|
|
138
187
|
/**
|
|
139
188
|
* Options accepted by `parseSkillRef`. The default (`allowTransient: true`)
|
|
140
189
|
* is the BFF submission parser path. The Blueprint parser passes
|
|
@@ -201,14 +250,20 @@ export declare function validateSkillBundleEntry(input: {
|
|
|
201
250
|
readonly mode?: number;
|
|
202
251
|
}): SkillBundleEntry;
|
|
203
252
|
/**
|
|
204
|
-
* Validate a full manifest. Enforces:
|
|
253
|
+
* Validate a full **skill bundle** manifest. Enforces:
|
|
205
254
|
* - entries is a non-empty array
|
|
206
|
-
* - `SKILL.md` exists at the bundle root (
|
|
255
|
+
* - `SKILL.md` exists at the bundle root (this is what makes a
|
|
256
|
+
* bundle a skill rather than a plain workspace file)
|
|
207
257
|
* - file count <= maxFiles
|
|
208
258
|
* - total uncompressed size <= maxDecompressedBytes
|
|
209
259
|
* - per-entry validation (see `validateSkillBundleEntry`)
|
|
210
260
|
* - no duplicate paths
|
|
211
261
|
*
|
|
262
|
+
* Per the May-2026 decision log in
|
|
263
|
+
* `references/agent-context-uploads.md`, **skill** means "Claude
|
|
264
|
+
* Skill" — bundles without `SKILL.md` are not skills and must go
|
|
265
|
+
* through the `AgentsMd` or `File` upload concepts instead.
|
|
266
|
+
*
|
|
212
267
|
* Returns a canonical manifest with totals computed.
|
|
213
268
|
*/
|
|
214
269
|
export declare function validateSkillBundleManifest(input: ReadonlyArray<{
|
|
@@ -216,6 +271,19 @@ export declare function validateSkillBundleManifest(input: ReadonlyArray<{
|
|
|
216
271
|
readonly size: number;
|
|
217
272
|
readonly mode?: number;
|
|
218
273
|
}>): SkillBundleManifest;
|
|
274
|
+
/**
|
|
275
|
+
* Returns true when the manifest carries a `SKILL.md` entry at the
|
|
276
|
+
* bundle root. The presence of this file is Anthropic's
|
|
277
|
+
* skill-auto-discovery signal — bundles that have it are treated as
|
|
278
|
+
* Claude skills and mounted accordingly; bundles that don't are still
|
|
279
|
+
* usable agent context (AGENTS.md, settings files, folders of helper
|
|
280
|
+
* data) but the agent won't pick them up via the skills mechanism.
|
|
281
|
+
*
|
|
282
|
+
* The check is intentionally a separate, callable predicate (rather
|
|
283
|
+
* than baked into `validateSkillBundleManifest`) so the storage and
|
|
284
|
+
* the attach layers can remain independent.
|
|
285
|
+
*/
|
|
286
|
+
export declare function hasSkillMdAtRoot(manifest: SkillBundleManifest): boolean;
|
|
219
287
|
/**
|
|
220
288
|
* The non-secret half of an MCP server declaration. This is what enters
|
|
221
289
|
* the hashed submission, the run snapshot, and any audit log. `name`
|
|
@@ -105,6 +105,18 @@ export function isProviderSkillRef(ref) {
|
|
|
105
105
|
export function isTransientSkillRef(ref) {
|
|
106
106
|
return ref.kind === "transient";
|
|
107
107
|
}
|
|
108
|
+
export function isWorkspaceAgentsMdRef(ref) {
|
|
109
|
+
return ref.kind === "workspace_agentsmd";
|
|
110
|
+
}
|
|
111
|
+
export function isTransientAgentsMdRef(ref) {
|
|
112
|
+
return ref.kind === "transient_agentsmd";
|
|
113
|
+
}
|
|
114
|
+
export function isWorkspaceFileRef(ref) {
|
|
115
|
+
return ref.kind === "workspace_file";
|
|
116
|
+
}
|
|
117
|
+
export function isTransientFileRef(ref) {
|
|
118
|
+
return ref.kind === "transient_file";
|
|
119
|
+
}
|
|
108
120
|
/**
|
|
109
121
|
* Parse a `SkillRef` from untrusted input. Used by the BFF run parser
|
|
110
122
|
* and by the operations module when deserialising API responses. Throws
|
|
@@ -265,14 +277,20 @@ export function validateSkillBundleEntry(input) {
|
|
|
265
277
|
return { path, size: input.size, mode };
|
|
266
278
|
}
|
|
267
279
|
/**
|
|
268
|
-
* Validate a full manifest. Enforces:
|
|
280
|
+
* Validate a full **skill bundle** manifest. Enforces:
|
|
269
281
|
* - entries is a non-empty array
|
|
270
|
-
* - `SKILL.md` exists at the bundle root (
|
|
282
|
+
* - `SKILL.md` exists at the bundle root (this is what makes a
|
|
283
|
+
* bundle a skill rather than a plain workspace file)
|
|
271
284
|
* - file count <= maxFiles
|
|
272
285
|
* - total uncompressed size <= maxDecompressedBytes
|
|
273
286
|
* - per-entry validation (see `validateSkillBundleEntry`)
|
|
274
287
|
* - no duplicate paths
|
|
275
288
|
*
|
|
289
|
+
* Per the May-2026 decision log in
|
|
290
|
+
* `references/agent-context-uploads.md`, **skill** means "Claude
|
|
291
|
+
* Skill" — bundles without `SKILL.md` are not skills and must go
|
|
292
|
+
* through the `AgentsMd` or `File` upload concepts instead.
|
|
293
|
+
*
|
|
276
294
|
* Returns a canonical manifest with totals computed.
|
|
277
295
|
*/
|
|
278
296
|
export function validateSkillBundleManifest(input) {
|
|
@@ -302,10 +320,27 @@ export function validateSkillBundleManifest(input) {
|
|
|
302
320
|
entries.push(entry);
|
|
303
321
|
}
|
|
304
322
|
if (!hasSkillMd) {
|
|
305
|
-
throw new SkillBundleValidationError("bundle manifest must contain a 'SKILL.md' entry at the bundle root"
|
|
323
|
+
throw new SkillBundleValidationError("skill bundle manifest must contain a 'SKILL.md' entry at the bundle root. " +
|
|
324
|
+
"If you want to upload an instructions file or generic agent context, use " +
|
|
325
|
+
"AgentsMd or File instead — see references/agent-context-uploads.md");
|
|
306
326
|
}
|
|
307
327
|
return { entries, totalSize, fileCount: entries.length };
|
|
308
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* Returns true when the manifest carries a `SKILL.md` entry at the
|
|
331
|
+
* bundle root. The presence of this file is Anthropic's
|
|
332
|
+
* skill-auto-discovery signal — bundles that have it are treated as
|
|
333
|
+
* Claude skills and mounted accordingly; bundles that don't are still
|
|
334
|
+
* usable agent context (AGENTS.md, settings files, folders of helper
|
|
335
|
+
* data) but the agent won't pick them up via the skills mechanism.
|
|
336
|
+
*
|
|
337
|
+
* The check is intentionally a separate, callable predicate (rather
|
|
338
|
+
* than baked into `validateSkillBundleManifest`) so the storage and
|
|
339
|
+
* the attach layers can remain independent.
|
|
340
|
+
*/
|
|
341
|
+
export function hasSkillMdAtRoot(manifest) {
|
|
342
|
+
return manifest.entries.some((entry) => entry.path === "SKILL.md");
|
|
343
|
+
}
|
|
309
344
|
export const MCP_SERVER_NAME_PATTERN = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
310
345
|
export function parseMcpServerRef(input, path) {
|
|
311
346
|
if (input === null || typeof input !== "object" || Array.isArray(input)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HttpClient } from "./http.js";
|
|
2
2
|
import type { RunUnit } from "./run-unit.js";
|
|
3
|
-
import type { Output, Run, RunEvent, SignedOutputLink, Skill, WhoAmI } from "./runtime-types.js";
|
|
3
|
+
import type { AgentsMdRecord, FileRecord, Output, Run, RunEvent, SignedOutputLink, Skill, WhoAmI } from "./runtime-types.js";
|
|
4
4
|
import type { PlatformFlatRunSubmissionInput, PlatformRunSubmissionInput } from "./submission.js";
|
|
5
5
|
/**
|
|
6
6
|
* The single source of truth for SDK<->BFF transport. The SDK class
|
|
@@ -52,22 +52,32 @@ export declare function downloadRunArchive(http: HttpClient, runId: string): Pro
|
|
|
52
52
|
export declare function submitRunFlat(http: HttpClient, request: PlatformFlatRunSubmissionInput): Promise<Run>;
|
|
53
53
|
/**
|
|
54
54
|
* Multipart variant of `submitRunFlat` for runs that carry transient
|
|
55
|
-
* (per-run) skill bundles
|
|
56
|
-
* `submission` part; each `TransientSkillRef.slot` in
|
|
57
|
-
* `request.submission.skills` MUST be mirrored by exactly one
|
|
58
|
-
* `skill:<slot>` part with the bundle bytes.
|
|
55
|
+
* (per-run) skill bundles and/or transient AgentsMd content.
|
|
59
56
|
*
|
|
60
|
-
* The
|
|
61
|
-
*
|
|
62
|
-
*
|
|
57
|
+
* The JSON submission travels as the `submission` part; each
|
|
58
|
+
* `TransientSkillRef.slot` in `request.submission.skills` MUST be
|
|
59
|
+
* mirrored by exactly one `skill:<slot>` part with the bundle bytes.
|
|
60
|
+
* Each `TransientAgentsMdRef.slot` in `request.submission.agentsMd`
|
|
61
|
+
* MUST be mirrored by exactly one `agentsmd:<slot>` part with the
|
|
62
|
+
* markdown text.
|
|
63
63
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
64
|
+
* The BFF re-canonicalises and re-hashes each bundle/file; a
|
|
65
|
+
* `contentHash` mismatch is rejected with a deterministic error.
|
|
66
|
+
*
|
|
67
|
+
* At least one of `bundles` or `agentsMdParts` must be non-empty.
|
|
66
68
|
*/
|
|
67
69
|
export declare function submitRunFlatMultipart(http: HttpClient, request: PlatformFlatRunSubmissionInput, bundles: ReadonlyArray<{
|
|
68
70
|
readonly slot: string;
|
|
69
71
|
readonly bytes: Uint8Array;
|
|
70
72
|
readonly filename: string;
|
|
73
|
+
}>, agentsMdParts?: ReadonlyArray<{
|
|
74
|
+
readonly slot: string;
|
|
75
|
+
readonly content: string;
|
|
76
|
+
readonly filename: string;
|
|
77
|
+
}>, fileParts?: ReadonlyArray<{
|
|
78
|
+
readonly slot: string;
|
|
79
|
+
readonly bytes: Uint8Array;
|
|
80
|
+
readonly filename: string;
|
|
71
81
|
}>): Promise<Run>;
|
|
72
82
|
/**
|
|
73
83
|
* Upload a workspace skill bundle as a zip blob. The dashboard BFF runs
|
|
@@ -106,3 +116,68 @@ export declare function findSkillByHash(http: HttpClient, args: {
|
|
|
106
116
|
* indexed by-hash route is reserved for `uploadIfChanged`.
|
|
107
117
|
*/
|
|
108
118
|
export declare function findSkillByName(http: HttpClient, name: string): Promise<Skill | null>;
|
|
119
|
+
/**
|
|
120
|
+
* Upload a workspace AgentsMd file as a markdown string. The BFF
|
|
121
|
+
* canonicalises the content into a deterministic zip with AGENTS.md at
|
|
122
|
+
* root and runs the two-phase pending → ready upload.
|
|
123
|
+
*/
|
|
124
|
+
export declare function createAgentsMd(http: HttpClient, args: {
|
|
125
|
+
readonly name: string;
|
|
126
|
+
readonly content: string;
|
|
127
|
+
}): Promise<AgentsMdRecord>;
|
|
128
|
+
export declare function listAgentsMd(http: HttpClient): Promise<readonly AgentsMdRecord[]>;
|
|
129
|
+
export declare function getAgentsMd(http: HttpClient, agentsMdId: string): Promise<AgentsMdRecord>;
|
|
130
|
+
export declare function deleteAgentsMd(http: HttpClient, agentsMdId: string): Promise<void>;
|
|
131
|
+
/**
|
|
132
|
+
* Upload a workspace File as a zip bundle. The BFF canonicalises the
|
|
133
|
+
* content and runs the two-phase pending → ready upload.
|
|
134
|
+
*/
|
|
135
|
+
export declare function createFile(http: HttpClient, args: {
|
|
136
|
+
readonly name: string;
|
|
137
|
+
readonly bytes: Uint8Array;
|
|
138
|
+
}): Promise<FileRecord>;
|
|
139
|
+
export declare function listFiles(http: HttpClient): Promise<readonly FileRecord[]>;
|
|
140
|
+
export declare function getFile(http: HttpClient, fileId: string): Promise<FileRecord>;
|
|
141
|
+
export declare function deleteFile(http: HttpClient, fileId: string): Promise<void>;
|
|
142
|
+
/** Payload returned by the BFF's upload-init endpoint. */
|
|
143
|
+
export interface AssetUploadInitResult {
|
|
144
|
+
readonly assetId: string;
|
|
145
|
+
readonly storagePath: string;
|
|
146
|
+
readonly tusUrl: string;
|
|
147
|
+
readonly tusToken: string;
|
|
148
|
+
readonly expiresAt: string;
|
|
149
|
+
readonly uploadHeaders: Readonly<Record<string, string>>;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Initialise a chunked asset upload session. Calls the BFF's
|
|
153
|
+
* `POST /api/assets/upload-init` endpoint, which:
|
|
154
|
+
*
|
|
155
|
+
* 1. Inserts a `state='pending'` row in the appropriate table.
|
|
156
|
+
* 2. Returns a TUS URL + short-lived token the SDK will use to drive
|
|
157
|
+
* `tus-js-client` directly against Supabase Storage.
|
|
158
|
+
*
|
|
159
|
+
* The caller holds the `assetId` and `storagePath` for the subsequent
|
|
160
|
+
* finalize call.
|
|
161
|
+
*/
|
|
162
|
+
export declare function initAssetUpload(http: HttpClient, input: {
|
|
163
|
+
readonly kind: "skill" | "file";
|
|
164
|
+
readonly name: string;
|
|
165
|
+
readonly sizeBytes: number;
|
|
166
|
+
readonly hash: string;
|
|
167
|
+
}): Promise<AssetUploadInitResult>;
|
|
168
|
+
/**
|
|
169
|
+
* Finalise a chunked asset upload session. Calls the BFF's
|
|
170
|
+
* `POST /api/assets/finalize` endpoint, which:
|
|
171
|
+
*
|
|
172
|
+
* 1. Downloads the assembled bytes from Supabase Storage.
|
|
173
|
+
* 2. Verifies `sha256(bytes) === hash`.
|
|
174
|
+
* 3. Transitions the row `pending → ready`.
|
|
175
|
+
*
|
|
176
|
+
* Throws if the server returns a non-OK response (e.g. `hash_mismatch`).
|
|
177
|
+
*/
|
|
178
|
+
export declare function finalizeAssetUpload(http: HttpClient, input: {
|
|
179
|
+
readonly assetId: string;
|
|
180
|
+
readonly kind: "skill" | "file";
|
|
181
|
+
readonly hash: string;
|
|
182
|
+
readonly storagePath: string;
|
|
183
|
+
}): Promise<void>;
|
|
@@ -83,21 +83,26 @@ export async function submitRunFlat(http, request) {
|
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* Multipart variant of `submitRunFlat` for runs that carry transient
|
|
86
|
-
* (per-run) skill bundles
|
|
87
|
-
* `submission` part; each `TransientSkillRef.slot` in
|
|
88
|
-
* `request.submission.skills` MUST be mirrored by exactly one
|
|
89
|
-
* `skill:<slot>` part with the bundle bytes.
|
|
86
|
+
* (per-run) skill bundles and/or transient AgentsMd content.
|
|
90
87
|
*
|
|
91
|
-
* The
|
|
92
|
-
*
|
|
93
|
-
*
|
|
88
|
+
* The JSON submission travels as the `submission` part; each
|
|
89
|
+
* `TransientSkillRef.slot` in `request.submission.skills` MUST be
|
|
90
|
+
* mirrored by exactly one `skill:<slot>` part with the bundle bytes.
|
|
91
|
+
* Each `TransientAgentsMdRef.slot` in `request.submission.agentsMd`
|
|
92
|
+
* MUST be mirrored by exactly one `agentsmd:<slot>` part with the
|
|
93
|
+
* markdown text.
|
|
94
94
|
*
|
|
95
|
-
*
|
|
96
|
-
*
|
|
95
|
+
* The BFF re-canonicalises and re-hashes each bundle/file; a
|
|
96
|
+
* `contentHash` mismatch is rejected with a deterministic error.
|
|
97
|
+
*
|
|
98
|
+
* At least one of `bundles` or `agentsMdParts` must be non-empty.
|
|
97
99
|
*/
|
|
98
|
-
export async function submitRunFlatMultipart(http, request, bundles) {
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
export async function submitRunFlatMultipart(http, request, bundles, agentsMdParts, fileParts) {
|
|
101
|
+
const hasBundles = Array.isArray(bundles) && bundles.length > 0;
|
|
102
|
+
const hasAgentsMd = Array.isArray(agentsMdParts) && agentsMdParts.length > 0;
|
|
103
|
+
const hasFiles = Array.isArray(fileParts) && fileParts.length > 0;
|
|
104
|
+
if (!hasBundles && !hasAgentsMd && !hasFiles) {
|
|
105
|
+
throw new Error("submitRunFlatMultipart: bundles, agentsMdParts, or fileParts must be non-empty");
|
|
101
106
|
}
|
|
102
107
|
const form = new FormData();
|
|
103
108
|
// Submission rides as a typed JSON Blob so the BFF reads
|
|
@@ -116,6 +121,30 @@ export async function submitRunFlatMultipart(http, request, bundles) {
|
|
|
116
121
|
const blob = toBlob(bundle.bytes, "application/zip");
|
|
117
122
|
form.append(`skill:${bundle.slot}`, blob, bundle.filename);
|
|
118
123
|
}
|
|
124
|
+
for (const part of agentsMdParts ?? []) {
|
|
125
|
+
if (typeof part.slot !== "string" || !part.slot) {
|
|
126
|
+
throw new Error("submitRunFlatMultipart: each agentsMd part must have a non-empty slot id");
|
|
127
|
+
}
|
|
128
|
+
const partKey = `agentsmd:${part.slot}`;
|
|
129
|
+
if (seen.has(partKey)) {
|
|
130
|
+
throw new Error(`submitRunFlatMultipart: duplicate agentsMd slot "${part.slot}"`);
|
|
131
|
+
}
|
|
132
|
+
seen.add(partKey);
|
|
133
|
+
const blob = new Blob([part.content], { type: "text/plain" });
|
|
134
|
+
form.append(partKey, blob, part.filename);
|
|
135
|
+
}
|
|
136
|
+
for (const part of fileParts ?? []) {
|
|
137
|
+
if (typeof part.slot !== "string" || !part.slot) {
|
|
138
|
+
throw new Error("submitRunFlatMultipart: each file part must have a non-empty slot id");
|
|
139
|
+
}
|
|
140
|
+
const partKey = `file:${part.slot}`;
|
|
141
|
+
if (seen.has(partKey)) {
|
|
142
|
+
throw new Error(`submitRunFlatMultipart: duplicate file slot "${part.slot}"`);
|
|
143
|
+
}
|
|
144
|
+
seen.add(partKey);
|
|
145
|
+
const blob = toBlob(part.bytes, "application/zip");
|
|
146
|
+
form.append(partKey, blob, part.filename);
|
|
147
|
+
}
|
|
119
148
|
return http.request("/api/runs", {
|
|
120
149
|
method: "POST",
|
|
121
150
|
body: form
|
|
@@ -183,6 +212,80 @@ export async function findSkillByName(http, name) {
|
|
|
183
212
|
const skills = await listSkills(http);
|
|
184
213
|
return skills.find((skill) => skill.name === name) ?? null;
|
|
185
214
|
}
|
|
215
|
+
// ===========================================================================
|
|
216
|
+
// AgentsMd (workspace_files kind='agentsmd') operations
|
|
217
|
+
// ===========================================================================
|
|
218
|
+
/**
|
|
219
|
+
* Upload a workspace AgentsMd file as a markdown string. The BFF
|
|
220
|
+
* canonicalises the content into a deterministic zip with AGENTS.md at
|
|
221
|
+
* root and runs the two-phase pending → ready upload.
|
|
222
|
+
*/
|
|
223
|
+
export async function createAgentsMd(http, args) {
|
|
224
|
+
const form = new FormData();
|
|
225
|
+
form.append("name", args.name);
|
|
226
|
+
form.append("content", new Blob([args.content], { type: "text/plain" }), "AGENTS.md");
|
|
227
|
+
const result = await http.request("/api/agentsmd", { method: "POST", body: form });
|
|
228
|
+
return unwrapAgentsMd(result);
|
|
229
|
+
}
|
|
230
|
+
export async function listAgentsMd(http) {
|
|
231
|
+
const result = await http.request("/api/agentsmd");
|
|
232
|
+
if (Array.isArray(result)) {
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
return result.agentsMd;
|
|
236
|
+
}
|
|
237
|
+
export async function getAgentsMd(http, agentsMdId) {
|
|
238
|
+
const result = await http.request(`/api/agentsmd/${encodeURIComponent(agentsMdId)}`);
|
|
239
|
+
return unwrapAgentsMd(result);
|
|
240
|
+
}
|
|
241
|
+
export async function deleteAgentsMd(http, agentsMdId) {
|
|
242
|
+
await http.request(`/api/agentsmd/${encodeURIComponent(agentsMdId)}`, {
|
|
243
|
+
method: "DELETE"
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function unwrapAgentsMd(result) {
|
|
247
|
+
if (result && typeof result === "object" && "agentsMd" in result) {
|
|
248
|
+
return result.agentsMd;
|
|
249
|
+
}
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
252
|
+
// ===========================================================================
|
|
253
|
+
// File (workspace_files kind='file') operations
|
|
254
|
+
// ===========================================================================
|
|
255
|
+
/**
|
|
256
|
+
* Upload a workspace File as a zip bundle. The BFF canonicalises the
|
|
257
|
+
* content and runs the two-phase pending → ready upload.
|
|
258
|
+
*/
|
|
259
|
+
export async function createFile(http, args) {
|
|
260
|
+
const form = new FormData();
|
|
261
|
+
form.append("name", args.name);
|
|
262
|
+
const blob = toBlob(args.bytes, "application/zip");
|
|
263
|
+
form.append("bundle", blob, `${args.name}.zip`);
|
|
264
|
+
const result = await http.request("/api/files", { method: "POST", body: form });
|
|
265
|
+
return unwrapFile(result);
|
|
266
|
+
}
|
|
267
|
+
export async function listFiles(http) {
|
|
268
|
+
const result = await http.request("/api/files");
|
|
269
|
+
if (Array.isArray(result)) {
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
return result.files;
|
|
273
|
+
}
|
|
274
|
+
export async function getFile(http, fileId) {
|
|
275
|
+
const result = await http.request(`/api/files/${encodeURIComponent(fileId)}`);
|
|
276
|
+
return unwrapFile(result);
|
|
277
|
+
}
|
|
278
|
+
export async function deleteFile(http, fileId) {
|
|
279
|
+
await http.request(`/api/files/${encodeURIComponent(fileId)}`, {
|
|
280
|
+
method: "DELETE"
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
function unwrapFile(result) {
|
|
284
|
+
if (result && typeof result === "object" && "file" in result) {
|
|
285
|
+
return result.file;
|
|
286
|
+
}
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
186
289
|
function unwrapSkill(result) {
|
|
187
290
|
if (result && typeof result === "object" && "skill" in result) {
|
|
188
291
|
return result.skill;
|
|
@@ -206,4 +309,37 @@ function toBlob(input, contentType) {
|
|
|
206
309
|
function hasRun(value) {
|
|
207
310
|
return Boolean(value && typeof value === "object" && "run" in value);
|
|
208
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* Initialise a chunked asset upload session. Calls the BFF's
|
|
314
|
+
* `POST /api/assets/upload-init` endpoint, which:
|
|
315
|
+
*
|
|
316
|
+
* 1. Inserts a `state='pending'` row in the appropriate table.
|
|
317
|
+
* 2. Returns a TUS URL + short-lived token the SDK will use to drive
|
|
318
|
+
* `tus-js-client` directly against Supabase Storage.
|
|
319
|
+
*
|
|
320
|
+
* The caller holds the `assetId` and `storagePath` for the subsequent
|
|
321
|
+
* finalize call.
|
|
322
|
+
*/
|
|
323
|
+
export async function initAssetUpload(http, input) {
|
|
324
|
+
return http.request("/api/assets/upload-init", {
|
|
325
|
+
method: "POST",
|
|
326
|
+
body: JSON.stringify(input)
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Finalise a chunked asset upload session. Calls the BFF's
|
|
331
|
+
* `POST /api/assets/finalize` endpoint, which:
|
|
332
|
+
*
|
|
333
|
+
* 1. Downloads the assembled bytes from Supabase Storage.
|
|
334
|
+
* 2. Verifies `sha256(bytes) === hash`.
|
|
335
|
+
* 3. Transitions the row `pending → ready`.
|
|
336
|
+
*
|
|
337
|
+
* Throws if the server returns a non-OK response (e.g. `hash_mismatch`).
|
|
338
|
+
*/
|
|
339
|
+
export async function finalizeAssetUpload(http, input) {
|
|
340
|
+
await http.request("/api/assets/finalize", {
|
|
341
|
+
method: "POST",
|
|
342
|
+
body: JSON.stringify(input)
|
|
343
|
+
});
|
|
344
|
+
}
|
|
209
345
|
//# sourceMappingURL=operations.js.map
|
package/dist/_shared/run-unit.js
CHANGED
|
@@ -57,6 +57,8 @@ function parseFlatProjection(value) {
|
|
|
57
57
|
...(typeof submissionRaw.system === "string" ? { system: submissionRaw.system } : {}),
|
|
58
58
|
prompt: toStringArray(submissionRaw.prompt),
|
|
59
59
|
skills: toSkillRefArray(submissionRaw.skills),
|
|
60
|
+
agentsMd: [],
|
|
61
|
+
files: [],
|
|
60
62
|
mcpServers: toMcpServerRefArray(submissionRaw.mcpServers),
|
|
61
63
|
...(parseEnvironment(submissionRaw.environment)
|
|
62
64
|
? { environment: parseEnvironment(submissionRaw.environment) }
|
|
@@ -101,6 +103,8 @@ function fallbackFlat() {
|
|
|
101
103
|
model: "",
|
|
102
104
|
prompt: [],
|
|
103
105
|
skills: [],
|
|
106
|
+
agentsMd: [],
|
|
107
|
+
files: [],
|
|
104
108
|
mcpServers: []
|
|
105
109
|
}
|
|
106
110
|
};
|
|
@@ -122,6 +122,53 @@ export interface Skill {
|
|
|
122
122
|
readonly deletedAt?: string | null;
|
|
123
123
|
readonly [key: string]: unknown;
|
|
124
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Wire-level record for a workspace AgentsMd file as returned by the BFF.
|
|
127
|
+
* Mirrors `PublicWorkspaceFile` from the dashboard service layer.
|
|
128
|
+
*/
|
|
129
|
+
export interface AgentsMdRecord {
|
|
130
|
+
readonly id: string;
|
|
131
|
+
readonly kind?: "agentsmd";
|
|
132
|
+
readonly name: string;
|
|
133
|
+
readonly state: "pending" | "ready";
|
|
134
|
+
readonly hash?: string | null;
|
|
135
|
+
readonly sizeBytes?: number | null;
|
|
136
|
+
readonly fileCount?: number | null;
|
|
137
|
+
readonly manifest?: ReadonlyArray<{
|
|
138
|
+
readonly path: string;
|
|
139
|
+
readonly size: number;
|
|
140
|
+
readonly mode: number;
|
|
141
|
+
}>;
|
|
142
|
+
readonly createdAt?: string;
|
|
143
|
+
readonly updatedAt?: string;
|
|
144
|
+
readonly finalizedAt?: string | null;
|
|
145
|
+
readonly deletedAt?: string | null;
|
|
146
|
+
readonly [key: string]: unknown;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Wire-level record for a workspace File as returned by the BFF.
|
|
150
|
+
* Mirrors `PublicWorkspaceFile` from the dashboard service layer
|
|
151
|
+
* with kind='file' and `f_*` ids.
|
|
152
|
+
*/
|
|
153
|
+
export interface FileRecord {
|
|
154
|
+
readonly id: string;
|
|
155
|
+
readonly kind?: "file";
|
|
156
|
+
readonly name: string;
|
|
157
|
+
readonly state: "pending" | "ready";
|
|
158
|
+
readonly hash?: string | null;
|
|
159
|
+
readonly sizeBytes?: number | null;
|
|
160
|
+
readonly fileCount?: number | null;
|
|
161
|
+
readonly manifest?: ReadonlyArray<{
|
|
162
|
+
readonly path: string;
|
|
163
|
+
readonly size: number;
|
|
164
|
+
readonly mode: number;
|
|
165
|
+
}>;
|
|
166
|
+
readonly createdAt?: string;
|
|
167
|
+
readonly updatedAt?: string;
|
|
168
|
+
readonly finalizedAt?: string | null;
|
|
169
|
+
readonly deletedAt?: string | null;
|
|
170
|
+
readonly [key: string]: unknown;
|
|
171
|
+
}
|
|
125
172
|
/**
|
|
126
173
|
* Full submission as the SDK and CLI assemble it before posting. The
|
|
127
174
|
* `template` is the SDK-level ResolvedTemplate (or a JSON-encoded one);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ProxyAuthShape, type ProxyMethod, type ProxyResponseMode } from "./proxy-protocol.js";
|
|
2
|
-
import type { McpServerRef, SkillRef } from "./blueprint.js";
|
|
2
|
+
import type { AgentsMdRef, FileRef, McpServerRef, SkillRef } from "./blueprint.js";
|
|
3
3
|
export type JsonPrimitive = string | number | boolean | null;
|
|
4
4
|
export type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
5
5
|
readonly [key: string]: JsonValue;
|
|
@@ -172,6 +172,8 @@ export interface PlatformFlatSubmission {
|
|
|
172
172
|
readonly system?: string;
|
|
173
173
|
readonly prompt: readonly string[];
|
|
174
174
|
readonly skills: readonly SkillRef[];
|
|
175
|
+
readonly agentsMd: readonly AgentsMdRef[];
|
|
176
|
+
readonly files: readonly FileRef[];
|
|
175
177
|
readonly mcpServers: readonly McpServerRef[];
|
|
176
178
|
readonly environment?: PlatformTemplateEnvironment;
|
|
177
179
|
readonly metadata?: Record<string, JsonValue>;
|