antpath 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,131 @@
1
+ import { authShapeHeaderName, PROXY_RESPONSE_MODES } from "./_shared/index.js";
2
+ export class ProxyEndpoint {
3
+ /** Non-secret half of the wire shape — declaration only. */
4
+ declaration;
5
+ /** Per-request secret half — auth value keyed by the same `name`. */
6
+ auth;
7
+ constructor(declaration, auth) {
8
+ this.declaration = declaration;
9
+ this.auth = auth;
10
+ }
11
+ /** Bearer-token endpoint. */
12
+ static bearer(options) {
13
+ const common = buildCommonDeclaration(options, { type: "bearer" });
14
+ requireNonEmpty(options.token, "ProxyEndpoint.bearer: token is required");
15
+ return new ProxyEndpoint(common, {
16
+ name: common.name,
17
+ value: { type: "bearer", token: options.token }
18
+ });
19
+ }
20
+ /** Basic-auth endpoint. */
21
+ static basic(options) {
22
+ const common = buildCommonDeclaration(options, { type: "basic" });
23
+ requireNonEmpty(options.username, "ProxyEndpoint.basic: username is required");
24
+ requireNonEmpty(options.password, "ProxyEndpoint.basic: password is required");
25
+ return new ProxyEndpoint(common, {
26
+ name: common.name,
27
+ value: { type: "basic", username: options.username, password: options.password }
28
+ });
29
+ }
30
+ /** Custom-header endpoint. */
31
+ static header(options) {
32
+ requireNonEmpty(options.header, "ProxyEndpoint.header: header is required");
33
+ const common = buildCommonDeclaration(options, { type: "header", name: options.header });
34
+ requireNonEmpty(options.value, "ProxyEndpoint.header: value is required");
35
+ return new ProxyEndpoint(common, {
36
+ name: common.name,
37
+ value: { type: "header", value: options.value }
38
+ });
39
+ }
40
+ /** Query-string-auth endpoint. */
41
+ static query(options) {
42
+ requireNonEmpty(options.query, "ProxyEndpoint.query: query is required");
43
+ const common = buildCommonDeclaration(options, { type: "query", name: options.query });
44
+ requireNonEmpty(options.value, "ProxyEndpoint.query: value is required");
45
+ return new ProxyEndpoint(common, {
46
+ name: common.name,
47
+ value: { type: "query", value: options.value }
48
+ });
49
+ }
50
+ }
51
+ /**
52
+ * Split a list of `ProxyEndpoint` instances into the public declarations
53
+ * (`proxyEndpoints[]`) and the per-request auth bundle
54
+ * (`secrets.proxyEndpointAuth[]`). Mirrors the way `submitRun` already
55
+ * splits `McpServer.headers` into `secrets.mcpServers[]`.
56
+ *
57
+ * Throws on duplicate endpoint names — names are the cross-reference
58
+ * key between the two halves and the BFF rejects collisions; failing
59
+ * here gives the caller a precise message at the call site instead of
60
+ * an opaque HTTP error.
61
+ */
62
+ export function splitProxyEndpoints(inputs) {
63
+ if (inputs.length === 0) {
64
+ return { endpoints: [], auth: [] };
65
+ }
66
+ const endpoints = [];
67
+ const auth = [];
68
+ const seen = new Set();
69
+ for (let i = 0; i < inputs.length; i++) {
70
+ const entry = inputs[i];
71
+ if (!(entry instanceof ProxyEndpoint)) {
72
+ throw new TypeError(`proxyEndpoints[${i}] must be a ProxyEndpoint built via ProxyEndpoint.bearer / header / basic / query`);
73
+ }
74
+ if (seen.has(entry.declaration.name)) {
75
+ throw new Error(`proxyEndpoints duplicate name: ${entry.declaration.name}`);
76
+ }
77
+ seen.add(entry.declaration.name);
78
+ endpoints.push(entry.declaration);
79
+ auth.push(entry.auth);
80
+ }
81
+ return { endpoints, auth };
82
+ }
83
+ function buildCommonDeclaration(options, authShape) {
84
+ requireNonEmpty(options.name, "ProxyEndpoint: name is required");
85
+ requireNonEmpty(options.baseUrl, "ProxyEndpoint: baseUrl is required");
86
+ if (!Array.isArray(options.allowMethods) || options.allowMethods.length === 0) {
87
+ throw new Error("ProxyEndpoint: allowMethods must be a non-empty array");
88
+ }
89
+ if (!Array.isArray(options.allowPathPrefixes) || options.allowPathPrefixes.length === 0) {
90
+ throw new Error("ProxyEndpoint: allowPathPrefixes must be a non-empty array");
91
+ }
92
+ if (options.responseMode !== undefined && !PROXY_RESPONSE_MODES.includes(options.responseMode)) {
93
+ throw new Error(`ProxyEndpoint: responseMode must be one of ${PROXY_RESPONSE_MODES.join(" | ")}`);
94
+ }
95
+ // Defence in depth: don't let the caller list the auth carrier
96
+ // header in `allowHeaders`. The BFF rejects this too, but a precise
97
+ // SDK-side error message is clearer.
98
+ if (options.allowHeaders) {
99
+ const carrier = authShapeHeaderName(authShape);
100
+ if (carrier) {
101
+ for (const h of options.allowHeaders) {
102
+ if (h.toLowerCase() === carrier) {
103
+ throw new Error(`ProxyEndpoint: allowHeaders MUST NOT include the auth header "${h}" — ` +
104
+ `it's set by the proxy on every request`);
105
+ }
106
+ }
107
+ }
108
+ }
109
+ return {
110
+ name: options.name,
111
+ baseUrl: options.baseUrl,
112
+ authShape,
113
+ allowMethods: options.allowMethods,
114
+ allowPathPrefixes: options.allowPathPrefixes,
115
+ ...(options.allowHeaders ? { allowHeaders: options.allowHeaders } : {}),
116
+ ...(options.responseMode ? { responseMode: options.responseMode } : {}),
117
+ ...(options.maxRequestBytes !== undefined ? { maxRequestBytes: options.maxRequestBytes } : {}),
118
+ ...(options.maxResponseBytes !== undefined ? { maxResponseBytes: options.maxResponseBytes } : {}),
119
+ ...(options.timeoutMs !== undefined ? { timeoutMs: options.timeoutMs } : {}),
120
+ ...(options.perCallBudget !== undefined ? { perCallBudget: options.perCallBudget } : {}),
121
+ ...(options.responseByteBudget !== undefined
122
+ ? { responseByteBudget: options.responseByteBudget }
123
+ : {})
124
+ };
125
+ }
126
+ function requireNonEmpty(value, message) {
127
+ if (typeof value !== "string" || !value) {
128
+ throw new Error(message);
129
+ }
130
+ }
131
+ //# sourceMappingURL=proxy-endpoint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-endpoint.js","sourceRoot":"","sources":["../src/proxy-endpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EAOrB,MAAM,iBAAiB,CAAC;AAwFzB,MAAM,OAAO,aAAa;IACxB,4DAA4D;IACnD,WAAW,CAAwB;IAC5C,qEAAqE;IAC5D,IAAI,CAA4B;IAEzC,YAAoB,WAAkC,EAAE,IAA+B;QACrF,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,6BAA6B;IAC7B,MAAM,CAAC,MAAM,CAAC,OAAmC;QAC/C,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACnE,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,yCAAyC,CAAC,CAAC;QAC1E,OAAO,IAAI,aAAa,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE;SAChD,CAAC,CAAC;IACL,CAAC;IAED,2BAA2B;IAC3B,MAAM,CAAC,KAAK,CAAC,OAAkC;QAC7C,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QAClE,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,2CAA2C,CAAC,CAAC;QAC/E,eAAe,CAAC,OAAO,CAAC,QAAQ,EAAE,2CAA2C,CAAC,CAAC;QAC/E,OAAO,IAAI,aAAa,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE;SACjF,CAAC,CAAC;IACL,CAAC;IAED,8BAA8B;IAC9B,MAAM,CAAC,MAAM,CAAC,OAAmC;QAC/C,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,0CAA0C,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QACzF,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,yCAAyC,CAAC,CAAC;QAC1E,OAAO,IAAI,aAAa,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE;SAChD,CAAC,CAAC;IACL,CAAC;IAED,kCAAkC;IAClC,MAAM,CAAC,KAAK,CAAC,OAAkC;QAC7C,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,wCAAwC,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,sBAAsB,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACvF,eAAe,CAAC,OAAO,CAAC,KAAK,EAAE,wCAAwC,CAAC,CAAC;QACzE,OAAO,IAAI,aAAa,CAAC,MAAM,EAAE;YAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE;SAC/C,CAAC,CAAC;IACL,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAgC;IAIlE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IACD,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,MAAM,IAAI,GAAgC,EAAE,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,CAAC,KAAK,YAAY,aAAa,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,SAAS,CACjB,kBAAkB,CAAC,mFAAmF,CACvG,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACjC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,SAAS,sBAAsB,CAC7B,OAAmC,EACnC,SAAyB;IAEzB,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,iCAAiC,CAAC,CAAC;IACjE,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,oCAAoC,CAAC,CAAC;IACvE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,OAAO,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxF,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAChF,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/F,MAAM,IAAI,KAAK,CACb,8CAA8C,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACjF,CAAC;IACJ,CAAC;IACD,+DAA+D;IAC/D,oEAAoE;IACpE,qCAAqC;IACrC,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;gBACrC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,OAAO,EAAE,CAAC;oBAChC,MAAM,IAAI,KAAK,CACb,iEAAiE,CAAC,MAAM;wBACtE,wCAAwC,CAC3C,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS;QACT,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvE,GAAG,CAAC,OAAO,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9F,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjG,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,GAAG,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,GAAG,CAAC,OAAO,CAAC,kBAAkB,KAAK,SAAS;YAC1C,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,CAAC,kBAAkB,EAAE;YACpD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,KAAc,EAAE,OAAe;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC"}
package/dist/skill.d.ts CHANGED
@@ -1,40 +1,80 @@
1
- import type { ProviderSkillRef, Skill as SkillRecord, SkillRef } from "./_shared/index.js";
1
+ import { type ProviderSkillRef, type Skill as SkillRecord, type SkillRef } from "./_shared/index.js";
2
+ import { type SkillFiles } from "./bundle.js";
2
3
  /**
3
- * Workspace `Skill` and provider `Skill` are both modeled by ONE class with
4
- * a discriminated wire shape under `.ref`. Keeping a single class means
5
- * `submitRun({ skills: [...] })` accepts a uniform array; the SDK
6
- * normalises every entry to its `ref` before sending the wire payload.
7
- *
8
- * Three workspace constructors:
9
- *
10
- * - `Skill.fromId("skl_abc123")` — reference an existing workspace
11
- * skill without re-uploading. Useful for sharing a skill across many
12
- * `submitRun` calls or in a `defineRun` factory.
13
- * - `client.skills.upload({ name, files })` inline files map (UTF-8
14
- * strings or `Uint8Array`); SDK zips and uploads.
15
- * - `client.skills.fromPath("./dir", { name })` — local directory; SDK
16
- * reads, zips, and uploads (Node only).
17
- *
18
- * One provider constructor:
19
- *
20
- * - `Skill.provider({ vendor, skillId, version? })` references a
21
- * provider built-in skill (e.g. Anthropic web-search). Provider
22
- * skills are NOT uploaded to your workspace and have no
23
- * soft-delete semantics.
24
- *
25
- * Instances are immutable. The wire `ref` is the only state and never
26
- * carries credentials.
4
+ * One `Skill` class, one mental model, three usage modes:
5
+ *
6
+ * - **Workspace** uploaded to the antpath platform and reused across
7
+ * runs.
8
+ * ```ts
9
+ * const persisted = await Skill.fromFiles({ name, files }).upload(client);
10
+ * // or
11
+ * const ref = Skill.fromId("skl_abc123");
12
+ * ```
13
+ *
14
+ * - **Provider built-in** references a provider-side skill (e.g.
15
+ * Anthropic web-search). Not uploaded to your workspace.
16
+ * ```ts
17
+ * const websearch = Skill.provider({ vendor: "anthropic", skillId: "web-search" });
18
+ * ```
19
+ *
20
+ * - **Transient (per-run)** — built from local files, never persisted.
21
+ * The bytes ride alongside `submitRun` as a multipart part and the
22
+ * BFF tears them down at run terminal.
23
+ * ```ts
24
+ * const rules = await Skill.fromFiles({ name: "rules", files: {...} });
25
+ * await client.submitRun({ skills: [rules], ... });
26
+ * ```
27
+ *
28
+ * ## Lifecycle of an unstaged transient Skill
29
+ *
30
+ * After `Skill.fromFiles(...)` returns, the Skill is "unstaged transient":
31
+ *
32
+ * 1. Passing it to `submitRun` uploads the bytes for that one run only
33
+ * and assigns a positional slot id (`transient-0`, `transient-1`, …).
34
+ * The same instance may be passed to multiple `submitRun` calls
35
+ * until it is consumed by `.upload(...)`.
36
+ *
37
+ * 2. Calling `await skill.upload(client)` persists the bundle to the
38
+ * workspace skill store and returns a **new** `Skill` instance
39
+ * whose `.ref.kind === "workspace"`. The **original** is marked
40
+ * **consumed**:
41
+ * - any further use in `submitRun` throws a clear validation error,
42
+ * - `.upload(...)` on the consumed instance throws,
43
+ * - `JSON.stringify` / `toJSON()` on the consumed instance throws.
44
+ *
45
+ * Use the returned (workspace) Skill from then on. The consumed
46
+ * reference exists only to surface the mistake loudly the first
47
+ * time the user re-uses it; it never silently re-uploads as
48
+ * transient.
49
+ *
50
+ * Unstaged transient Skills do NOT round-trip through JSON (the bytes
51
+ * cannot be serialised back). `toJSON()` throws in that state too —
52
+ * persist via `.upload(client)` first, or pass the unstaged Skill
53
+ * directly to `submitRun`.
54
+ *
55
+ * The Skill class is the only public way to build a transient bundle;
56
+ * the SDK never accepts a raw `TransientSkillRef` object from user code.
27
57
  */
28
58
  export declare class Skill {
59
+ #private;
29
60
  /** Workspace skill record returned by the BFF (only set for workspace-uploaded skills). */
30
61
  readonly record: SkillRecord | undefined;
31
- readonly ref: SkillRef;
32
62
  /**
33
- * Internal constructor. Use `Skill.fromId`, `Skill.provider`, or
34
- * `client.skills.upload` / `client.skills.fromPath` to create
35
- * instances.
63
+ * Internal constructor. Use `Skill.fromId`, `Skill.provider`,
64
+ * `Skill.fromFiles`, or `Skill.fromPath` to create instances.
36
65
  */
37
- constructor(ref: SkillRef, record?: SkillRecord);
66
+ constructor(ref: SkillRef, record?: SkillRecord, transientBytes?: Uint8Array);
67
+ /**
68
+ * The wire-level reference. For workspace and provider skills this is
69
+ * stable. For unstaged transient skills it carries the placeholder
70
+ * `slot: "(unstaged)"` — `submitRun` rewrites the slot to a real
71
+ * positional id (`transient-0`, …) before sending.
72
+ *
73
+ * For consumed Skills, the getter still returns the original
74
+ * transient ref so error messages can be precise — but using a
75
+ * consumed Skill in any submit/serialise path throws.
76
+ */
77
+ get ref(): SkillRef;
38
78
  /**
39
79
  * Reference an existing workspace skill by its id (e.g. `skl_abc123`).
40
80
  * Does NOT validate the skill exists — that check happens on the next
@@ -52,8 +92,99 @@ export declare class Skill {
52
92
  readonly skillId: string;
53
93
  readonly version?: string;
54
94
  }): Skill;
55
- /** True for `Skill.fromId(...)` and skills returned by `client.skills.upload(...)`. */
95
+ /**
96
+ * Build an unstaged transient Skill from an inline files map. The SDK
97
+ * validates basic safety (no path traversal, size caps, has
98
+ * `SKILL.md`), deterministically zips the bundle, and computes the
99
+ * `sha256:<hex>` content hash that travels in the wire ref.
100
+ *
101
+ * The returned Skill carries the bytes privately. Pass it to
102
+ * `submitRun` for transient (per-run) use, or call `.upload(client)`
103
+ * to persist it as a workspace skill.
104
+ */
105
+ static fromFiles(args: {
106
+ readonly name: string;
107
+ readonly files: SkillFiles;
108
+ }): Promise<Skill>;
109
+ /**
110
+ * Read a local directory and build an unstaged transient Skill.
111
+ * Symlinks and non-regular files are skipped. Node-only.
112
+ *
113
+ * The returned Skill behaves identically to one built via
114
+ * `Skill.fromFiles` — pass it to `submitRun` for transient use, or
115
+ * call `.upload(client)` to persist as a workspace skill.
116
+ */
117
+ static fromPath(rootDir: string, args: {
118
+ readonly name: string;
119
+ }): Promise<Skill>;
120
+ /**
121
+ * Persist this unstaged transient Skill as a workspace skill and
122
+ * return a new `Skill` instance backed by the resulting `skl_*`
123
+ * record. After `upload` resolves successfully, the original
124
+ * instance is marked **consumed** — any further use throws a clear
125
+ * validation error.
126
+ *
127
+ * Only unstaged transient Skills can be uploaded. Calling this on a
128
+ * workspace-ref Skill, a provider-ref Skill, or a previously
129
+ * consumed Skill throws.
130
+ *
131
+ * Accepts either an `AntpathClient` (preferred) or its
132
+ * `SkillsClient` if the caller already has a handle to it.
133
+ */
134
+ upload(client: SkillUploader): Promise<Skill>;
135
+ /** True for `Skill.fromId(...)` and skills returned by `.upload(...)`. */
56
136
  get isWorkspace(): boolean;
57
137
  /** True for `Skill.provider(...)`. */
58
138
  get isProvider(): boolean;
139
+ /** True for any transient Skill (unstaged or consumed). */
140
+ get isTransient(): boolean;
141
+ /**
142
+ * True only while the transient Skill still carries bytes and has
143
+ * not been consumed by `.upload(...)`. Unstaged Skills can be passed
144
+ * to `submitRun` or `.upload(client)`; consumed ones cannot.
145
+ */
146
+ get isUnstaged(): boolean;
147
+ /** True after a successful `.upload(...)` — using this instance further throws. */
148
+ get isConsumed(): boolean;
149
+ /**
150
+ * Internal: yield the unstaged transient bundle's payload so the
151
+ * client's `submitRun` can build a multipart part. Returns undefined
152
+ * for non-transient or consumed skills. Throws if the instance is
153
+ * marked consumed (a stronger signal than "no bytes").
154
+ *
155
+ * NOT part of the public API — the `_` prefix is a "do not call from
156
+ * user code" marker. Callers within the SDK pass the returned bytes
157
+ * into the multipart body once per `submitRun` invocation.
158
+ */
159
+ _takeUnstagedBundle(): {
160
+ name: string;
161
+ bytes: Uint8Array;
162
+ contentHash: string;
163
+ } | undefined;
164
+ /**
165
+ * JSON serialisation guard. Workspace and provider Skills serialise
166
+ * to their `ref`. Unstaged transient Skills throw — the bytes are not
167
+ * in the JSON, so a round-trip would silently drop them. Consumed
168
+ * Skills also throw, to surface the "you forgot to use the returned
169
+ * Skill from `.upload(...)`" mistake at the point it happens.
170
+ */
171
+ toJSON(): SkillRef;
172
+ }
173
+ /**
174
+ * Anything that can persist a skill bundle. Both `AntpathClient` and
175
+ * the internal `SkillsClient` satisfy this shape — `Skill.upload`
176
+ * accepts either, but the SDK consumer only ever sees the
177
+ * `AntpathClient`-based path.
178
+ */
179
+ export interface SkillUploader {
180
+ readonly _uploadSkillBundle?: (args: {
181
+ readonly name: string;
182
+ readonly body: Uint8Array;
183
+ }) => Promise<SkillRecord>;
184
+ readonly skills?: {
185
+ readonly _uploadSkillBundle?: (args: {
186
+ readonly name: string;
187
+ readonly body: Uint8Array;
188
+ }) => Promise<SkillRecord>;
189
+ };
59
190
  }
package/dist/skill.js CHANGED
@@ -1,41 +1,88 @@
1
+ import { SKILL_NAME_PATTERN } from "./_shared/index.js";
2
+ import { bundleSkillFiles, hashSkillBundle } from "./bundle.js";
3
+ import { readDirectoryAsFiles } from "./node-fs.js";
1
4
  /**
2
- * Workspace `Skill` and provider `Skill` are both modeled by ONE class with
3
- * a discriminated wire shape under `.ref`. Keeping a single class means
4
- * `submitRun({ skills: [...] })` accepts a uniform array; the SDK
5
- * normalises every entry to its `ref` before sending the wire payload.
5
+ * One `Skill` class, one mental model, three usage modes:
6
6
  *
7
- * Three workspace constructors:
7
+ * - **Workspace** uploaded to the antpath platform and reused across
8
+ * runs.
9
+ * ```ts
10
+ * const persisted = await Skill.fromFiles({ name, files }).upload(client);
11
+ * // or
12
+ * const ref = Skill.fromId("skl_abc123");
13
+ * ```
8
14
  *
9
- * - `Skill.fromId("skl_abc123")`reference an existing workspace
10
- * skill without re-uploading. Useful for sharing a skill across many
11
- * `submitRun` calls or in a `defineRun` factory.
12
- * - `client.skills.upload({ name, files })` — inline files map (UTF-8
13
- * strings or `Uint8Array`); SDK zips and uploads.
14
- * - `client.skills.fromPath("./dir", { name })` — local directory; SDK
15
- * reads, zips, and uploads (Node only).
15
+ * - **Provider built-in** references a provider-side skill (e.g.
16
+ * Anthropic web-search). Not uploaded to your workspace.
17
+ * ```ts
18
+ * const websearch = Skill.provider({ vendor: "anthropic", skillId: "web-search" });
19
+ * ```
16
20
  *
17
- * One provider constructor:
21
+ * - **Transient (per-run)** — built from local files, never persisted.
22
+ * The bytes ride alongside `submitRun` as a multipart part and the
23
+ * BFF tears them down at run terminal.
24
+ * ```ts
25
+ * const rules = await Skill.fromFiles({ name: "rules", files: {...} });
26
+ * await client.submitRun({ skills: [rules], ... });
27
+ * ```
18
28
  *
19
- * - `Skill.provider({ vendor, skillId, version? })` references a
20
- * provider built-in skill (e.g. Anthropic web-search). Provider
21
- * skills are NOT uploaded to your workspace and have no
22
- * soft-delete semantics.
29
+ * ## Lifecycle of an unstaged transient Skill
23
30
  *
24
- * Instances are immutable. The wire `ref` is the only state and never
25
- * carries credentials.
31
+ * After `Skill.fromFiles(...)` returns, the Skill is "unstaged transient":
32
+ *
33
+ * 1. Passing it to `submitRun` uploads the bytes for that one run only
34
+ * and assigns a positional slot id (`transient-0`, `transient-1`, …).
35
+ * The same instance may be passed to multiple `submitRun` calls
36
+ * until it is consumed by `.upload(...)`.
37
+ *
38
+ * 2. Calling `await skill.upload(client)` persists the bundle to the
39
+ * workspace skill store and returns a **new** `Skill` instance
40
+ * whose `.ref.kind === "workspace"`. The **original** is marked
41
+ * **consumed**:
42
+ * - any further use in `submitRun` throws a clear validation error,
43
+ * - `.upload(...)` on the consumed instance throws,
44
+ * - `JSON.stringify` / `toJSON()` on the consumed instance throws.
45
+ *
46
+ * Use the returned (workspace) Skill from then on. The consumed
47
+ * reference exists only to surface the mistake loudly the first
48
+ * time the user re-uses it; it never silently re-uploads as
49
+ * transient.
50
+ *
51
+ * Unstaged transient Skills do NOT round-trip through JSON (the bytes
52
+ * cannot be serialised back). `toJSON()` throws in that state too —
53
+ * persist via `.upload(client)` first, or pass the unstaged Skill
54
+ * directly to `submitRun`.
55
+ *
56
+ * The Skill class is the only public way to build a transient bundle;
57
+ * the SDK never accepts a raw `TransientSkillRef` object from user code.
26
58
  */
27
59
  export class Skill {
28
60
  /** Workspace skill record returned by the BFF (only set for workspace-uploaded skills). */
29
61
  record;
30
- ref;
62
+ #ref;
63
+ #transientBytes;
64
+ #consumed = false;
31
65
  /**
32
- * Internal constructor. Use `Skill.fromId`, `Skill.provider`, or
33
- * `client.skills.upload` / `client.skills.fromPath` to create
34
- * instances.
66
+ * Internal constructor. Use `Skill.fromId`, `Skill.provider`,
67
+ * `Skill.fromFiles`, or `Skill.fromPath` to create instances.
35
68
  */
36
- constructor(ref, record) {
37
- this.ref = ref;
69
+ constructor(ref, record, transientBytes) {
70
+ this.#ref = ref;
38
71
  this.record = record;
72
+ this.#transientBytes = transientBytes;
73
+ }
74
+ /**
75
+ * The wire-level reference. For workspace and provider skills this is
76
+ * stable. For unstaged transient skills it carries the placeholder
77
+ * `slot: "(unstaged)"` — `submitRun` rewrites the slot to a real
78
+ * positional id (`transient-0`, …) before sending.
79
+ *
80
+ * For consumed Skills, the getter still returns the original
81
+ * transient ref so error messages can be precise — but using a
82
+ * consumed Skill in any submit/serialise path throws.
83
+ */
84
+ get ref() {
85
+ return this.#ref;
39
86
  }
40
87
  /**
41
88
  * Reference an existing workspace skill by its id (e.g. `skl_abc123`).
@@ -47,8 +94,7 @@ export class Skill {
47
94
  if (typeof id !== "string" || !id) {
48
95
  throw new Error("Skill.fromId: id is required");
49
96
  }
50
- const ref = { kind: "workspace", id };
51
- return new Skill(ref);
97
+ return new Skill({ kind: "workspace", id });
52
98
  }
53
99
  /**
54
100
  * Reference a provider built-in skill. The vendor decides what the
@@ -70,13 +116,162 @@ export class Skill {
70
116
  : { kind: "provider", vendor: args.vendor, skillId: args.skillId };
71
117
  return new Skill(ref);
72
118
  }
73
- /** True for `Skill.fromId(...)` and skills returned by `client.skills.upload(...)`. */
119
+ /**
120
+ * Build an unstaged transient Skill from an inline files map. The SDK
121
+ * validates basic safety (no path traversal, size caps, has
122
+ * `SKILL.md`), deterministically zips the bundle, and computes the
123
+ * `sha256:<hex>` content hash that travels in the wire ref.
124
+ *
125
+ * The returned Skill carries the bytes privately. Pass it to
126
+ * `submitRun` for transient (per-run) use, or call `.upload(client)`
127
+ * to persist it as a workspace skill.
128
+ */
129
+ static async fromFiles(args) {
130
+ if (!args || typeof args !== "object") {
131
+ throw new Error("Skill.fromFiles: args is required");
132
+ }
133
+ if (typeof args.name !== "string" || !SKILL_NAME_PATTERN.test(args.name)) {
134
+ throw new Error(`Skill.fromFiles: name must match ${SKILL_NAME_PATTERN.source}`);
135
+ }
136
+ const bundled = bundleSkillFiles(args.files);
137
+ const contentHash = await hashSkillBundle(bundled.zip);
138
+ const ref = {
139
+ kind: "transient",
140
+ slot: UNSTAGED_SLOT,
141
+ name: args.name,
142
+ contentHash
143
+ };
144
+ return new Skill(ref, undefined, bundled.zip);
145
+ }
146
+ /**
147
+ * Read a local directory and build an unstaged transient Skill.
148
+ * Symlinks and non-regular files are skipped. Node-only.
149
+ *
150
+ * The returned Skill behaves identically to one built via
151
+ * `Skill.fromFiles` — pass it to `submitRun` for transient use, or
152
+ * call `.upload(client)` to persist as a workspace skill.
153
+ */
154
+ static async fromPath(rootDir, args) {
155
+ const files = await readDirectoryAsFiles(rootDir);
156
+ return Skill.fromFiles({ name: args.name, files });
157
+ }
158
+ /**
159
+ * Persist this unstaged transient Skill as a workspace skill and
160
+ * return a new `Skill` instance backed by the resulting `skl_*`
161
+ * record. After `upload` resolves successfully, the original
162
+ * instance is marked **consumed** — any further use throws a clear
163
+ * validation error.
164
+ *
165
+ * Only unstaged transient Skills can be uploaded. Calling this on a
166
+ * workspace-ref Skill, a provider-ref Skill, or a previously
167
+ * consumed Skill throws.
168
+ *
169
+ * Accepts either an `AntpathClient` (preferred) or its
170
+ * `SkillsClient` if the caller already has a handle to it.
171
+ */
172
+ async upload(client) {
173
+ if (this.#consumed) {
174
+ throw new Error(consumedMessage());
175
+ }
176
+ if (this.#ref.kind !== "transient" || !this.#transientBytes) {
177
+ throw new Error("Skill.upload: only unstaged transient Skills (built via Skill.fromFiles / Skill.fromPath) can be uploaded; " +
178
+ "use Skill.fromId(record.id) to reference an already-persisted skill");
179
+ }
180
+ const uploader = resolveUploader(client);
181
+ const record = await uploader({ name: this.#ref.name, body: this.#transientBytes });
182
+ // Only mark consumed AFTER a successful upload — a failed upload
183
+ // leaves the original instance reusable so the caller can retry.
184
+ this.#consumed = true;
185
+ return new Skill({ kind: "workspace", id: record.id }, record);
186
+ }
187
+ /** True for `Skill.fromId(...)` and skills returned by `.upload(...)`. */
74
188
  get isWorkspace() {
75
- return this.ref.kind === "workspace";
189
+ return this.#ref.kind === "workspace";
76
190
  }
77
191
  /** True for `Skill.provider(...)`. */
78
192
  get isProvider() {
79
- return this.ref.kind === "provider";
193
+ return this.#ref.kind === "provider";
194
+ }
195
+ /** True for any transient Skill (unstaged or consumed). */
196
+ get isTransient() {
197
+ return this.#ref.kind === "transient";
198
+ }
199
+ /**
200
+ * True only while the transient Skill still carries bytes and has
201
+ * not been consumed by `.upload(...)`. Unstaged Skills can be passed
202
+ * to `submitRun` or `.upload(client)`; consumed ones cannot.
203
+ */
204
+ get isUnstaged() {
205
+ return (this.#ref.kind === "transient" &&
206
+ this.#ref.slot === UNSTAGED_SLOT &&
207
+ !this.#consumed &&
208
+ this.#transientBytes !== undefined);
209
+ }
210
+ /** True after a successful `.upload(...)` — using this instance further throws. */
211
+ get isConsumed() {
212
+ return this.#consumed;
80
213
  }
214
+ /**
215
+ * Internal: yield the unstaged transient bundle's payload so the
216
+ * client's `submitRun` can build a multipart part. Returns undefined
217
+ * for non-transient or consumed skills. Throws if the instance is
218
+ * marked consumed (a stronger signal than "no bytes").
219
+ *
220
+ * NOT part of the public API — the `_` prefix is a "do not call from
221
+ * user code" marker. Callers within the SDK pass the returned bytes
222
+ * into the multipart body once per `submitRun` invocation.
223
+ */
224
+ _takeUnstagedBundle() {
225
+ if (this.#consumed) {
226
+ throw new Error(consumedMessage());
227
+ }
228
+ if (!this.isUnstaged) {
229
+ return undefined;
230
+ }
231
+ if (this.#ref.kind !== "transient" || !this.#transientBytes) {
232
+ return undefined;
233
+ }
234
+ return {
235
+ name: this.#ref.name,
236
+ bytes: this.#transientBytes,
237
+ contentHash: this.#ref.contentHash
238
+ };
239
+ }
240
+ /**
241
+ * JSON serialisation guard. Workspace and provider Skills serialise
242
+ * to their `ref`. Unstaged transient Skills throw — the bytes are not
243
+ * in the JSON, so a round-trip would silently drop them. Consumed
244
+ * Skills also throw, to surface the "you forgot to use the returned
245
+ * Skill from `.upload(...)`" mistake at the point it happens.
246
+ */
247
+ toJSON() {
248
+ if (this.#consumed) {
249
+ throw new Error(consumedMessage());
250
+ }
251
+ if (this.isUnstaged) {
252
+ throw new Error("Cannot JSON-serialise an unstaged transient Skill — the bytes are not in the JSON. " +
253
+ "Persist via skill.upload(client) and serialise the returned (workspace) Skill, " +
254
+ "or pass the unstaged Skill directly to submitRun without serialising.");
255
+ }
256
+ return this.#ref;
257
+ }
258
+ }
259
+ /** Sentinel slot id used by unstaged transient Skills. */
260
+ const UNSTAGED_SLOT = "(unstaged)";
261
+ function resolveUploader(client) {
262
+ const direct = client._uploadSkillBundle;
263
+ if (typeof direct === "function") {
264
+ return direct.bind(client);
265
+ }
266
+ const nested = client.skills?._uploadSkillBundle;
267
+ if (typeof nested === "function") {
268
+ return nested.bind(client.skills);
269
+ }
270
+ throw new Error("Skill.upload: client argument does not expose an upload entry point — " +
271
+ "pass the AntpathClient instance or its `client.skills`");
272
+ }
273
+ function consumedMessage() {
274
+ return ("this Skill was already uploaded via skill.upload(client); use the returned Skill or " +
275
+ "Skill.fromId(record.id) for subsequent runs");
81
276
  }
82
277
  //# sourceMappingURL=skill.js.map
package/dist/skill.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,OAAO,KAAK;IAChB,2FAA2F;IAClF,MAAM,CAA0B;IAChC,GAAG,CAAW;IAEvB;;;;OAIG;IACH,YAAY,GAAa,EAAE,MAAoB;QAC7C,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,MAAM,CAAC,EAAU;QACtB,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QACD,MAAM,GAAG,GAAsB,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QACzD,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,IAA0G;QACxH,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,GAAG,GAAqB,IAAI,CAAC,OAAO;YACxC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;YACzF,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QACrE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,uFAAuF;IACvF,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,WAAW,CAAC;IACvC,CAAC;IAED,sCAAsC;IACtC,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC;IACtC,CAAC;CACF"}
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../src/skill.ts"],"names":[],"mappings":"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"}