@agent-api/sdk 1.0.5 → 1.0.8
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 +21 -0
- package/README.md +4 -2
- package/dist/local-skills.d.ts +1 -0
- package/dist/local-skills.js +144 -26
- package/dist/resources/skills.d.ts +9 -2
- package/dist/resources/skills.js +187 -2
- package/dist/types/input.d.ts +1 -1
- package/dist/types/skills.d.ts +83 -1
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog — @agent-api/sdk
|
|
2
2
|
|
|
3
|
+
## 1.0.8
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Expanded `reasoning.effort` types to match the Responses-compatible enum: `none`, `minimal`, `low`, `medium`, `high`, and `xhigh`.
|
|
8
|
+
|
|
9
|
+
## 1.0.7
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Skill artifact archive APIs: `client.skills.exportArchive()` and `client.skills.importArchive()`.
|
|
14
|
+
- Local directory sync helpers for platform skills: `client.skills.pushDirectory()` and `client.skills.pullDirectory()`.
|
|
15
|
+
- Skill branch diff API and file-level `acceptDev()` strategies (`patch` or `mirror`).
|
|
16
|
+
|
|
17
|
+
## 1.0.6
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Replaced skill focus `max_manifest_bytes` with `max_manifest_chars`.
|
|
22
|
+
- Local skill `SKILL.md` manifests are decoded as strict UTF-8 and truncated by characters.
|
|
23
|
+
|
|
3
24
|
## 1.0.5
|
|
4
25
|
|
|
5
26
|
### Added
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Production JavaScript/TypeScript SDK for the Managed Agent API.
|
|
4
4
|
|
|
5
|
-
**Published on npm:** [`@agent-api/sdk`](https://www.npmjs.com/package/@agent-api/sdk) (v1.0.
|
|
5
|
+
**Published on npm:** [`@agent-api/sdk`](https://www.npmjs.com/package/@agent-api/sdk) (v1.0.8)
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -60,7 +60,7 @@ src/
|
|
|
60
60
|
| `client.presets` | `list` |
|
|
61
61
|
| `client.tools` | `list` |
|
|
62
62
|
| `client.volumes` | `list`, `create`, `retrieve`, `update`, `delete`, `listEntries`, `searchEntries`, `readFile`, `writeFile`, `deletePath`, `reconcileUsage`, `createDirectory`, `downloadArchive`, `summarize`, `readLines`, `patchLines`, `grep` |
|
|
63
|
-
| `client.skills` | `list`, `create`, `discover`, `focus`, `createDev`, `updateFile`, `retrieve`, `update`, `archive`, `delete`, `acceptDev`, `discardDev`, `listFiles`, `readFile`, `writeFile`, `deleteFile` |
|
|
63
|
+
| `client.skills` | `list`, `create`, `discover`, `focus`, `createDev`, `updateFile`, `retrieve`, `update`, `archive`, `delete`, `diff`, `acceptDev`, `discardDev`, `exportArchive`, `importArchive`, `pushDirectory`, `pullDirectory`, `listFiles`, `readFile`, `writeFile`, `deleteFile` |
|
|
64
64
|
|
|
65
65
|
## Durable Volumes
|
|
66
66
|
|
|
@@ -80,6 +80,8 @@ const response = await client.agent.create({
|
|
|
80
80
|
|
|
81
81
|
## Skills
|
|
82
82
|
|
|
83
|
+
`localSkillFromDirectory()` reads `SKILL.md` into the descriptor for initial local-skill auto-focus; later focused reads still use the local skill tool bridge.
|
|
84
|
+
|
|
83
85
|
```typescript
|
|
84
86
|
import { localSkillFromDirectory } from "@agent-api/sdk";
|
|
85
87
|
|
package/dist/local-skills.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export interface LocalSkillDirectoryOptions {
|
|
|
5
5
|
id?: string;
|
|
6
6
|
name?: string;
|
|
7
7
|
description?: string;
|
|
8
|
+
max_manifest_chars?: number;
|
|
8
9
|
metadata?: Record<string, unknown>;
|
|
9
10
|
}
|
|
10
11
|
export declare function localSkillFromDirectory(rootDir: string, options?: LocalSkillDirectoryOptions): Promise<LocalSkillDescriptor>;
|
package/dist/local-skills.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { functionCallOutputInput, pendingFunctionCalls } from "./local-functions.js";
|
|
2
|
+
const DEFAULT_FOCUS_MANIFEST_CHARS = 16000;
|
|
3
|
+
const DEFAULT_FOCUS_FILE_CHARS = 12000;
|
|
2
4
|
export async function localSkillFromDirectory(rootDir, options = {}) {
|
|
3
5
|
const fs = await import("node:fs/promises");
|
|
4
6
|
const path = await import("node:path");
|
|
@@ -14,12 +16,17 @@ export async function localSkillFromDirectory(rootDir, options = {}) {
|
|
|
14
16
|
}
|
|
15
17
|
const digest = "sha256:" + hash.digest("hex");
|
|
16
18
|
const base = path.basename(root);
|
|
19
|
+
const localSkillID = options.id ?? base;
|
|
20
|
+
const { manifest, manifestTruncated } = await readLocalManifest(fs, path, root, options.max_manifest_chars ?? DEFAULT_FOCUS_MANIFEST_CHARS);
|
|
17
21
|
return {
|
|
18
|
-
local_skill_id:
|
|
22
|
+
local_skill_id: localSkillID,
|
|
23
|
+
skill_ref: skillRefForLocal(localSkillID, digest),
|
|
19
24
|
name: options.name ?? base,
|
|
20
25
|
description: options.description,
|
|
21
26
|
root_hint: root,
|
|
22
27
|
digest,
|
|
28
|
+
manifest,
|
|
29
|
+
manifest_truncated: manifestTruncated,
|
|
23
30
|
metadata: options.metadata,
|
|
24
31
|
};
|
|
25
32
|
}
|
|
@@ -27,17 +34,18 @@ export function pendingLocalSkillCalls(response) {
|
|
|
27
34
|
return pendingFunctionCalls(response).filter((call) => call.name === "skill_focus");
|
|
28
35
|
}
|
|
29
36
|
export async function runLocalSkillHandlers(response, localSkills) {
|
|
30
|
-
const
|
|
37
|
+
const byRef = await localSkillsByRef(localSkills);
|
|
31
38
|
const outputs = [];
|
|
32
39
|
for (const call of pendingLocalSkillCalls(response)) {
|
|
33
40
|
const args = call.arguments ? JSON.parse(call.arguments) : {};
|
|
34
|
-
const payload = await focusLocalSkills(args,
|
|
41
|
+
const payload = await focusLocalSkills(args, byRef);
|
|
35
42
|
outputs.push(functionCallOutputInput(call.call_id, payload));
|
|
36
43
|
}
|
|
37
44
|
return outputs;
|
|
38
45
|
}
|
|
39
|
-
async function focusLocalSkills(args,
|
|
40
|
-
const
|
|
46
|
+
async function focusLocalSkills(args, byRef) {
|
|
47
|
+
const maxManifestChars = manifestCharLimit(args);
|
|
48
|
+
const maxFileChars = fileCharLimit(args);
|
|
41
49
|
const items = Array.isArray(args.skills) ? args.skills : [];
|
|
42
50
|
if (!Array.isArray(args.skills)) {
|
|
43
51
|
return { data: [{ ok: false, error: { code: "invalid_skill_focus", message: "skills must be an array" } }] };
|
|
@@ -49,16 +57,16 @@ async function focusLocalSkills(args, byID) {
|
|
|
49
57
|
continue;
|
|
50
58
|
}
|
|
51
59
|
const item = raw;
|
|
52
|
-
const
|
|
53
|
-
const result = { ok: false,
|
|
54
|
-
const descriptor =
|
|
60
|
+
const skillRef = String(item.skill_ref || "").trim();
|
|
61
|
+
const result = { ok: false, skill_ref: skillRef, branch: "main" };
|
|
62
|
+
const descriptor = byRef.get(skillRef);
|
|
55
63
|
if (!descriptor) {
|
|
56
|
-
result.error = { code: "
|
|
64
|
+
result.error = { code: "skill_ref_not_found", message: "skill_ref was not registered with the SDK" };
|
|
57
65
|
data.push(result);
|
|
58
66
|
continue;
|
|
59
67
|
}
|
|
60
68
|
try {
|
|
61
|
-
result.skill = await focusedLocalSkill(descriptor,
|
|
69
|
+
result.skill = await focusedLocalSkill(descriptor, maxManifestChars, pathsArg(item), maxFileChars, includeManifest(item));
|
|
62
70
|
result.ok = true;
|
|
63
71
|
}
|
|
64
72
|
catch (error) {
|
|
@@ -68,9 +76,10 @@ async function focusLocalSkills(args, byID) {
|
|
|
68
76
|
}
|
|
69
77
|
return { data };
|
|
70
78
|
}
|
|
71
|
-
async function focusedLocalSkill(descriptor,
|
|
79
|
+
async function focusedLocalSkill(descriptor, maxManifestChars, paths, maxFileChars, includeManifest) {
|
|
72
80
|
const fs = await import("node:fs/promises");
|
|
73
81
|
const path = await import("node:path");
|
|
82
|
+
const { TextDecoder } = await import("node:util");
|
|
74
83
|
const root = path.resolve(descriptor.root_hint || ".");
|
|
75
84
|
const stat = await fs.stat(root);
|
|
76
85
|
if (!stat.isDirectory()) {
|
|
@@ -78,17 +87,20 @@ async function focusedLocalSkill(descriptor, maxManifestBytes) {
|
|
|
78
87
|
}
|
|
79
88
|
let manifest = "";
|
|
80
89
|
let manifestTruncated = false;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
if (includeManifest) {
|
|
91
|
+
try {
|
|
92
|
+
const manifestBytes = await fs.readFile(path.join(root, "SKILL.md"));
|
|
93
|
+
manifest = new TextDecoder("utf-8", { fatal: true }).decode(manifestBytes);
|
|
94
|
+
const manifestChars = Array.from(manifest);
|
|
95
|
+
if (maxManifestChars > 0 && manifestChars.length > maxManifestChars) {
|
|
96
|
+
manifest = manifestChars.slice(0, maxManifestChars).join("");
|
|
97
|
+
manifestTruncated = true;
|
|
98
|
+
}
|
|
86
99
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
throw error;
|
|
100
|
+
catch (error) {
|
|
101
|
+
if (error?.code !== "ENOENT") {
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
92
104
|
}
|
|
93
105
|
}
|
|
94
106
|
const dirents = await fs.readdir(root, { withFileTypes: true });
|
|
@@ -106,20 +118,72 @@ async function focusedLocalSkill(descriptor, maxManifestBytes) {
|
|
|
106
118
|
};
|
|
107
119
|
}));
|
|
108
120
|
return {
|
|
109
|
-
|
|
110
|
-
local_skill_id: descriptor.local_skill_id,
|
|
121
|
+
skill_ref: await descriptorSkillRef(descriptor),
|
|
111
122
|
name: descriptor.name || "",
|
|
112
123
|
description: descriptor.description || "",
|
|
113
124
|
branch: "SKILL_BRANCH_MAIN",
|
|
114
125
|
digest: descriptor.digest || "",
|
|
115
|
-
artifact_uri: "local://" + root.replace(/^\/+/, ""),
|
|
116
|
-
mount_hint: root,
|
|
117
126
|
manifest,
|
|
118
127
|
manifest_truncated: manifestTruncated,
|
|
119
128
|
entries,
|
|
120
|
-
|
|
129
|
+
files: await Promise.all(paths.map((relPath) => focusedLocalFile(fs, path, root, relPath, maxFileChars))),
|
|
121
130
|
};
|
|
122
131
|
}
|
|
132
|
+
function manifestCharLimit(args) {
|
|
133
|
+
const raw = args.max_manifest_chars ?? DEFAULT_FOCUS_MANIFEST_CHARS;
|
|
134
|
+
const value = Number(raw);
|
|
135
|
+
return Number.isFinite(value) ? value : DEFAULT_FOCUS_MANIFEST_CHARS;
|
|
136
|
+
}
|
|
137
|
+
function fileCharLimit(args) {
|
|
138
|
+
const raw = args.max_file_chars ?? DEFAULT_FOCUS_FILE_CHARS;
|
|
139
|
+
const value = Number(raw);
|
|
140
|
+
return Number.isFinite(value) ? value : DEFAULT_FOCUS_FILE_CHARS;
|
|
141
|
+
}
|
|
142
|
+
function pathsArg(item) {
|
|
143
|
+
if (!Array.isArray(item.paths)) {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
return item.paths
|
|
147
|
+
.filter((value) => typeof value === "string")
|
|
148
|
+
.map((value) => value.trim())
|
|
149
|
+
.filter(Boolean);
|
|
150
|
+
}
|
|
151
|
+
function includeManifest(item) {
|
|
152
|
+
return typeof item.include_manifest === "boolean" ? item.include_manifest : true;
|
|
153
|
+
}
|
|
154
|
+
async function focusedLocalFile(fs, path, root, relPath, maxFileChars) {
|
|
155
|
+
const base = { path: relPath, branch: "SKILL_BRANCH_MAIN", content: "", truncated: false, size: 0 };
|
|
156
|
+
const { TextDecoder } = await import("node:util");
|
|
157
|
+
try {
|
|
158
|
+
const full = path.resolve(root, relPath);
|
|
159
|
+
const relative = path.relative(root, full);
|
|
160
|
+
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
161
|
+
return { ...base, error: { type: "skill_error", code: "invalid_skill_file_path", message: "path must stay inside the local skill root" } };
|
|
162
|
+
}
|
|
163
|
+
const stat = await fs.stat(full);
|
|
164
|
+
if (!stat.isFile()) {
|
|
165
|
+
return { ...base, error: { type: "skill_error", code: "skill_file_not_found", message: "skill file was not found" } };
|
|
166
|
+
}
|
|
167
|
+
const raw = await fs.readFile(full);
|
|
168
|
+
let content = new TextDecoder("utf-8", { fatal: true }).decode(raw);
|
|
169
|
+
let truncated = false;
|
|
170
|
+
const chars = Array.from(content);
|
|
171
|
+
if (maxFileChars > 0 && chars.length > maxFileChars) {
|
|
172
|
+
content = chars.slice(0, maxFileChars).join("");
|
|
173
|
+
truncated = true;
|
|
174
|
+
}
|
|
175
|
+
return { ...base, content, truncated, size: stat.size };
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (error?.code === "ENOENT") {
|
|
179
|
+
return { ...base, error: { type: "skill_error", code: "skill_file_not_found", message: "skill file was not found" } };
|
|
180
|
+
}
|
|
181
|
+
if (error instanceof TypeError) {
|
|
182
|
+
return { ...base, error: { type: "skill_error", code: "invalid_skill_file_utf8", message: "skill file must be valid UTF-8" } };
|
|
183
|
+
}
|
|
184
|
+
return { ...base, error: { type: "skill_error", code: "skill_file_read_failed", message: error instanceof Error ? error.message : String(error) } };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
123
187
|
async function walkFiles(fs, path, root, dir) {
|
|
124
188
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
125
189
|
const out = [];
|
|
@@ -138,3 +202,57 @@ async function walkFiles(fs, path, root, dir) {
|
|
|
138
202
|
}
|
|
139
203
|
return out;
|
|
140
204
|
}
|
|
205
|
+
async function localSkillsByRef(localSkills) {
|
|
206
|
+
const out = new Map();
|
|
207
|
+
for (const skill of localSkills) {
|
|
208
|
+
out.set(await descriptorSkillRef(skill), skill);
|
|
209
|
+
}
|
|
210
|
+
return out;
|
|
211
|
+
}
|
|
212
|
+
async function descriptorSkillRef(descriptor) {
|
|
213
|
+
const existing = String(descriptor.skill_ref || "").trim();
|
|
214
|
+
if (existing) {
|
|
215
|
+
return existing;
|
|
216
|
+
}
|
|
217
|
+
return skillRefForLocal(descriptor.local_skill_id || "", descriptor.digest || "");
|
|
218
|
+
}
|
|
219
|
+
function skillRefForLocal(localSkillID, digest) {
|
|
220
|
+
const slug = skillRefSlug(localSkillID) || "local-skill";
|
|
221
|
+
const digestPart = skillRefDigestPart(digest) || "unknown";
|
|
222
|
+
return `local::${slug}@${digestPart}::main`;
|
|
223
|
+
}
|
|
224
|
+
function skillRefSlug(raw) {
|
|
225
|
+
return raw
|
|
226
|
+
.trim()
|
|
227
|
+
.toLowerCase()
|
|
228
|
+
.replace(/::/g, "-")
|
|
229
|
+
.replace(/@/g, "-")
|
|
230
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
231
|
+
.replace(/^[-_]+|[-_]+$/g, "")
|
|
232
|
+
.slice(0, 64)
|
|
233
|
+
.replace(/^[-_]+|[-_]+$/g, "");
|
|
234
|
+
}
|
|
235
|
+
function skillRefDigestPart(raw) {
|
|
236
|
+
const digest = raw.trim().toLowerCase().split(":").pop() || "";
|
|
237
|
+
return digest.replace(/[^a-z0-9_-]+/g, "").slice(0, 16);
|
|
238
|
+
}
|
|
239
|
+
async function readLocalManifest(fs, path, root, maxManifestChars) {
|
|
240
|
+
const { TextDecoder } = await import("node:util");
|
|
241
|
+
try {
|
|
242
|
+
const raw = await fs.readFile(path.join(root, "SKILL.md"));
|
|
243
|
+
let manifest = new TextDecoder("utf-8", { fatal: true }).decode(raw);
|
|
244
|
+
let manifestTruncated = false;
|
|
245
|
+
const chars = Array.from(manifest);
|
|
246
|
+
if (maxManifestChars > 0 && chars.length > maxManifestChars) {
|
|
247
|
+
manifest = chars.slice(0, maxManifestChars).join("");
|
|
248
|
+
manifestTruncated = true;
|
|
249
|
+
}
|
|
250
|
+
return { manifest, manifestTruncated };
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
if (error?.code === "ENOENT") {
|
|
254
|
+
return { manifest: "", manifestTruncated: false };
|
|
255
|
+
}
|
|
256
|
+
throw error;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { HTTPClient } from "../internal/http.js";
|
|
2
2
|
import type { RequestOptions } from "../types/common.js";
|
|
3
|
-
import type { CreateSkillParams, CreateSkillDevParams, CreateSkillDevResponse, DiscoverSkillsParams, FocusSkillParams, ListSkillFilesParams, ListSkillFilesResponse, ListSkillsParams, ListSkillsResponse, ListSkillSummariesResponse, Skill, SkillFile, SkillBranch, SkillFocusResponse, UpdateSkillFilePrimitiveParams, UpdateSkillFilePrimitiveResponse, UpdateSkillParams } from "../types/skills.js";
|
|
3
|
+
import type { CreateSkillParams, CreateSkillDevParams, CreateSkillDevResponse, DiscoverSkillsParams, FocusSkillParams, ImportSkillArchiveParams, ListSkillFilesParams, ListSkillFilesResponse, ListSkillsParams, ListSkillsResponse, ListSkillSummariesResponse, PullSkillDirectoryParams, PushSkillDirectoryParams, Skill, SkillAcceptStrategy, SkillArchive, SkillArchiveParams, SkillBranchDiff, SkillBranchDiffParams, SkillDirectoryPullResult, SkillFile, SkillBranch, SkillFocusResponse, SkillImportResponse, UpdateSkillFilePrimitiveParams, UpdateSkillFilePrimitiveResponse, UpdateSkillParams } from "../types/skills.js";
|
|
4
4
|
export declare class SkillsResource {
|
|
5
5
|
private readonly http;
|
|
6
6
|
constructor(http: HTTPClient);
|
|
@@ -16,7 +16,9 @@ export declare class SkillsResource {
|
|
|
16
16
|
delete(skillID: string, options?: RequestOptions): Promise<{
|
|
17
17
|
deleted: boolean;
|
|
18
18
|
}>;
|
|
19
|
-
acceptDev(skillID: string,
|
|
19
|
+
acceptDev(skillID: string, params?: {
|
|
20
|
+
strategy?: SkillAcceptStrategy;
|
|
21
|
+
}, options?: RequestOptions): Promise<Skill>;
|
|
20
22
|
discardDev(skillID: string, options?: RequestOptions): Promise<Skill>;
|
|
21
23
|
listFiles(skillID: string, params?: ListSkillFilesParams, options?: RequestOptions): Promise<ListSkillFilesResponse>;
|
|
22
24
|
readFile(skillID: string, path: string, params?: {
|
|
@@ -30,4 +32,9 @@ export declare class SkillsResource {
|
|
|
30
32
|
deleteFile(skillID: string, path: string, params?: {
|
|
31
33
|
branch?: SkillBranch;
|
|
32
34
|
}, options?: RequestOptions): Promise<SkillFile>;
|
|
35
|
+
exportArchive(skillID: string, params?: SkillArchiveParams, options?: RequestOptions): Promise<SkillArchive>;
|
|
36
|
+
importArchive(skillID: string, archive: ArrayBuffer | Blob, params?: ImportSkillArchiveParams, options?: RequestOptions): Promise<SkillImportResponse>;
|
|
37
|
+
diff(skillID: string, params?: SkillBranchDiffParams, options?: RequestOptions): Promise<SkillBranchDiff>;
|
|
38
|
+
pushDirectory(skillID: string, rootDir: string, params?: PushSkillDirectoryParams, options?: RequestOptions): Promise<SkillImportResponse>;
|
|
39
|
+
pullDirectory(skillID: string, targetDir: string, params?: PullSkillDirectoryParams, options?: RequestOptions): Promise<SkillDirectoryPullResult>;
|
|
33
40
|
}
|
package/dist/resources/skills.js
CHANGED
|
@@ -38,8 +38,8 @@ export class SkillsResource {
|
|
|
38
38
|
delete(skillID, options) {
|
|
39
39
|
return this.http.request("DELETE", `/v1/skills/${encodeURIComponent(skillID)}`, undefined, options);
|
|
40
40
|
}
|
|
41
|
-
acceptDev(skillID, options) {
|
|
42
|
-
return this.http.request("POST", `/v1/skills/${encodeURIComponent(skillID)}/accept_dev`, {}, options);
|
|
41
|
+
acceptDev(skillID, params = {}, options) {
|
|
42
|
+
return this.http.request("POST", `/v1/skills/${encodeURIComponent(skillID)}/accept_dev${buildQuery({ strategy: params.strategy })}`, {}, options);
|
|
43
43
|
}
|
|
44
44
|
discardDev(skillID, options) {
|
|
45
45
|
return this.http.request("POST", `/v1/skills/${encodeURIComponent(skillID)}/discard_dev`, {}, options);
|
|
@@ -66,6 +66,43 @@ export class SkillsResource {
|
|
|
66
66
|
deleteFile(skillID, path, params = {}, options) {
|
|
67
67
|
return this.http.request("DELETE", `/v1/skills/${encodeURIComponent(skillID)}/files/${skillPath(path)}${buildQuery({ branch: params.branch })}`, undefined, options);
|
|
68
68
|
}
|
|
69
|
+
exportArchive(skillID, params = {}, options) {
|
|
70
|
+
const archivePath = normalizeArchivePath(params.path);
|
|
71
|
+
return this.http
|
|
72
|
+
.requestBinary("GET", `/v1/skills/${encodeURIComponent(skillID)}/export${buildQuery({
|
|
73
|
+
path: archivePath || undefined,
|
|
74
|
+
branch: params.branch,
|
|
75
|
+
fallback_to_main: params.fallback_to_main === false ? "false" : undefined,
|
|
76
|
+
})}`, options)
|
|
77
|
+
.then(({ body, headers }) => ({
|
|
78
|
+
path: archivePath,
|
|
79
|
+
content: body,
|
|
80
|
+
content_type: headers.get("Content-Type") ?? undefined,
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
importArchive(skillID, archive, params = {}, options) {
|
|
84
|
+
return this.http.requestRaw("POST", `/v1/skills/${encodeURIComponent(skillID)}/import${buildQuery({
|
|
85
|
+
path: normalizeArchivePath(params.path) || undefined,
|
|
86
|
+
branch: params.branch,
|
|
87
|
+
replace: params.replace ? "true" : undefined,
|
|
88
|
+
strip_top_level_dir: params.strip_top_level_dir === false ? "false" : undefined,
|
|
89
|
+
})}`, archive, options);
|
|
90
|
+
}
|
|
91
|
+
diff(skillID, params = {}, options) {
|
|
92
|
+
return this.http.request("GET", `/v1/skills/${encodeURIComponent(skillID)}/diff${buildQuery({
|
|
93
|
+
path: normalizeArchivePath(params.path) || undefined,
|
|
94
|
+
max_file_chars: params.max_file_chars,
|
|
95
|
+
include_unchanged: params.include_unchanged ? "true" : undefined,
|
|
96
|
+
})}`, undefined, options);
|
|
97
|
+
}
|
|
98
|
+
async pushDirectory(skillID, rootDir, params = {}, options) {
|
|
99
|
+
const archive = await zipDirectory(rootDir);
|
|
100
|
+
return this.importArchive(skillID, archive, params, options);
|
|
101
|
+
}
|
|
102
|
+
async pullDirectory(skillID, targetDir, params = {}, options) {
|
|
103
|
+
const archive = await this.exportArchive(skillID, params, options);
|
|
104
|
+
return extractStoredZipToDirectory(archive.content, targetDir, { replace: params.replace === true });
|
|
105
|
+
}
|
|
69
106
|
}
|
|
70
107
|
function skillPath(path) {
|
|
71
108
|
return path
|
|
@@ -74,3 +111,151 @@ function skillPath(path) {
|
|
|
74
111
|
.map((part) => encodeURIComponent(part))
|
|
75
112
|
.join("/");
|
|
76
113
|
}
|
|
114
|
+
function normalizeArchivePath(path) {
|
|
115
|
+
return (path ?? "").trim().replace(/^\/+|\/+$/g, "");
|
|
116
|
+
}
|
|
117
|
+
async function zipDirectory(rootDir) {
|
|
118
|
+
const fs = await import("node:fs/promises");
|
|
119
|
+
const path = await import("node:path");
|
|
120
|
+
const root = path.resolve(rootDir);
|
|
121
|
+
const files = await walkArchiveFiles(fs, path, root, root);
|
|
122
|
+
const entries = [];
|
|
123
|
+
for (const rel of files.sort()) {
|
|
124
|
+
const content = await fs.readFile(path.join(root, rel));
|
|
125
|
+
entries.push({ path: rel, data: new Uint8Array(content.buffer, content.byteOffset, content.byteLength) });
|
|
126
|
+
}
|
|
127
|
+
return createStoredZip(entries);
|
|
128
|
+
}
|
|
129
|
+
async function walkArchiveFiles(fs, path, root, dir) {
|
|
130
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
131
|
+
const out = [];
|
|
132
|
+
for (const entry of entries) {
|
|
133
|
+
if (entry.name === ".git" || entry.name === "__pycache__" || entry.name === "node_modules") {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const full = path.join(dir, entry.name);
|
|
137
|
+
if (entry.isDirectory()) {
|
|
138
|
+
out.push(...await walkArchiveFiles(fs, path, root, full));
|
|
139
|
+
}
|
|
140
|
+
else if (entry.isFile()) {
|
|
141
|
+
out.push(path.relative(root, full).split(path.sep).join("/"));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return out;
|
|
145
|
+
}
|
|
146
|
+
async function extractStoredZipToDirectory(archive, targetDir, opts) {
|
|
147
|
+
const fs = await import("node:fs/promises");
|
|
148
|
+
const path = await import("node:path");
|
|
149
|
+
const root = path.resolve(targetDir);
|
|
150
|
+
if (opts.replace) {
|
|
151
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
152
|
+
}
|
|
153
|
+
await fs.mkdir(root, { recursive: true });
|
|
154
|
+
let fileCount = 0;
|
|
155
|
+
let byteCount = 0;
|
|
156
|
+
for (const entry of parseStoredZip(archive)) {
|
|
157
|
+
const dest = path.resolve(root, entry.path);
|
|
158
|
+
const rel = path.relative(root, dest);
|
|
159
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
160
|
+
throw new Error(`archive entry escapes target directory: ${entry.path}`);
|
|
161
|
+
}
|
|
162
|
+
await fs.mkdir(path.dirname(dest), { recursive: true });
|
|
163
|
+
await fs.writeFile(dest, entry.data);
|
|
164
|
+
fileCount += 1;
|
|
165
|
+
byteCount += entry.data.byteLength;
|
|
166
|
+
}
|
|
167
|
+
return { path: root, file_count: fileCount, byte_count: byteCount };
|
|
168
|
+
}
|
|
169
|
+
function createStoredZip(entries) {
|
|
170
|
+
const encoder = new TextEncoder();
|
|
171
|
+
const localParts = [];
|
|
172
|
+
const centralParts = [];
|
|
173
|
+
let offset = 0;
|
|
174
|
+
for (const entry of entries) {
|
|
175
|
+
const name = encoder.encode(entry.path);
|
|
176
|
+
const crc = crc32(entry.data);
|
|
177
|
+
const local = new Uint8Array(30 + name.length);
|
|
178
|
+
const lv = new DataView(local.buffer);
|
|
179
|
+
lv.setUint32(0, 0x04034b50, true);
|
|
180
|
+
lv.setUint16(4, 20, true);
|
|
181
|
+
lv.setUint16(8, 0, true);
|
|
182
|
+
lv.setUint32(14, crc, true);
|
|
183
|
+
lv.setUint32(18, entry.data.byteLength, true);
|
|
184
|
+
lv.setUint32(22, entry.data.byteLength, true);
|
|
185
|
+
lv.setUint16(26, name.length, true);
|
|
186
|
+
local.set(name, 30);
|
|
187
|
+
localParts.push(local, entry.data);
|
|
188
|
+
const central = new Uint8Array(46 + name.length);
|
|
189
|
+
const cv = new DataView(central.buffer);
|
|
190
|
+
cv.setUint32(0, 0x02014b50, true);
|
|
191
|
+
cv.setUint16(4, 20, true);
|
|
192
|
+
cv.setUint16(6, 20, true);
|
|
193
|
+
cv.setUint32(16, crc, true);
|
|
194
|
+
cv.setUint32(20, entry.data.byteLength, true);
|
|
195
|
+
cv.setUint32(24, entry.data.byteLength, true);
|
|
196
|
+
cv.setUint16(28, name.length, true);
|
|
197
|
+
cv.setUint32(42, offset, true);
|
|
198
|
+
central.set(name, 46);
|
|
199
|
+
centralParts.push(central);
|
|
200
|
+
offset += local.byteLength + entry.data.byteLength;
|
|
201
|
+
}
|
|
202
|
+
const centralOffset = offset;
|
|
203
|
+
const centralSize = centralParts.reduce((sum, part) => sum + part.byteLength, 0);
|
|
204
|
+
const end = new Uint8Array(22);
|
|
205
|
+
const ev = new DataView(end.buffer);
|
|
206
|
+
ev.setUint32(0, 0x06054b50, true);
|
|
207
|
+
ev.setUint16(8, entries.length, true);
|
|
208
|
+
ev.setUint16(10, entries.length, true);
|
|
209
|
+
ev.setUint32(12, centralSize, true);
|
|
210
|
+
ev.setUint32(16, centralOffset, true);
|
|
211
|
+
const zip = concatUint8([...localParts, ...centralParts, end]);
|
|
212
|
+
return zip.buffer.slice(zip.byteOffset, zip.byteOffset + zip.byteLength);
|
|
213
|
+
}
|
|
214
|
+
function parseStoredZip(archive) {
|
|
215
|
+
const data = new Uint8Array(archive);
|
|
216
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
217
|
+
const entries = [];
|
|
218
|
+
let pos = 0;
|
|
219
|
+
const decoder = new TextDecoder();
|
|
220
|
+
while (pos + 4 <= data.byteLength && view.getUint32(pos, true) === 0x04034b50) {
|
|
221
|
+
const method = view.getUint16(pos + 8, true);
|
|
222
|
+
if (method !== 0) {
|
|
223
|
+
throw new Error("Only stored ZIP entries are supported by pullDirectory");
|
|
224
|
+
}
|
|
225
|
+
const compressedSize = view.getUint32(pos + 18, true);
|
|
226
|
+
const fileNameLength = view.getUint16(pos + 26, true);
|
|
227
|
+
const extraLength = view.getUint16(pos + 28, true);
|
|
228
|
+
const nameStart = pos + 30;
|
|
229
|
+
const contentStart = nameStart + fileNameLength + extraLength;
|
|
230
|
+
const contentEnd = contentStart + compressedSize;
|
|
231
|
+
if (contentEnd > data.byteLength) {
|
|
232
|
+
throw new Error("Invalid ZIP archive");
|
|
233
|
+
}
|
|
234
|
+
const name = decoder.decode(data.slice(nameStart, nameStart + fileNameLength)).replace(/\\/g, "/");
|
|
235
|
+
if (name && !name.endsWith("/") && !name.startsWith("__MACOSX/") && !name.split("/").includes("..")) {
|
|
236
|
+
entries.push({ path: name.replace(/^\/+/, ""), data: data.slice(contentStart, contentEnd) });
|
|
237
|
+
}
|
|
238
|
+
pos = contentEnd;
|
|
239
|
+
}
|
|
240
|
+
return entries;
|
|
241
|
+
}
|
|
242
|
+
function concatUint8(parts) {
|
|
243
|
+
const total = parts.reduce((sum, part) => sum + part.byteLength, 0);
|
|
244
|
+
const out = new Uint8Array(total);
|
|
245
|
+
let offset = 0;
|
|
246
|
+
for (const part of parts) {
|
|
247
|
+
out.set(part, offset);
|
|
248
|
+
offset += part.byteLength;
|
|
249
|
+
}
|
|
250
|
+
return out;
|
|
251
|
+
}
|
|
252
|
+
function crc32(data) {
|
|
253
|
+
let crc = 0xffffffff;
|
|
254
|
+
for (const byte of data) {
|
|
255
|
+
crc ^= byte;
|
|
256
|
+
for (let i = 0; i < 8; i += 1) {
|
|
257
|
+
crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
261
|
+
}
|
package/dist/types/input.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ export interface FunctionCallOutputInput {
|
|
|
37
37
|
export type InputItem = InputMessage | FunctionCallInput | FunctionCallOutputInput;
|
|
38
38
|
export type Input = string | InputItem[];
|
|
39
39
|
export interface ReasoningConfig {
|
|
40
|
-
effort?: "low" | "medium" | "high";
|
|
40
|
+
effort?: "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
|
|
41
41
|
}
|
|
42
42
|
export interface ResponseFormat {
|
|
43
43
|
type: "json_schema";
|
package/dist/types/skills.d.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
export type SkillSourceType = "SKILL_SOURCE_TYPE_PLATFORM" | "SKILL_SOURCE_TYPE_LOCAL" | "SKILL_SOURCE_TYPE_GENERATED" | string;
|
|
2
2
|
export type SkillBranch = "main" | "dev" | string;
|
|
3
|
+
export type SkillAcceptStrategy = "patch" | "mirror";
|
|
4
|
+
export type SkillBranchDiffStatus = "added" | "modified" | "deleted" | "unchanged" | string;
|
|
3
5
|
export interface SkillReference {
|
|
4
6
|
skill_id: string;
|
|
5
7
|
branch?: SkillBranch;
|
|
6
8
|
}
|
|
7
9
|
export interface LocalSkillDescriptor {
|
|
8
10
|
local_skill_id: string;
|
|
11
|
+
skill_ref?: string;
|
|
9
12
|
name?: string;
|
|
10
13
|
description?: string;
|
|
11
14
|
root_hint?: string;
|
|
12
15
|
digest?: string;
|
|
16
|
+
manifest?: string;
|
|
17
|
+
manifest_truncated?: boolean;
|
|
13
18
|
metadata?: Record<string, unknown>;
|
|
14
19
|
}
|
|
15
20
|
export interface Skill {
|
|
@@ -34,6 +39,7 @@ export interface Skill {
|
|
|
34
39
|
export interface SkillSummary {
|
|
35
40
|
object: "skill_summary";
|
|
36
41
|
skill_id: string;
|
|
42
|
+
skill_ref?: string;
|
|
37
43
|
name?: string;
|
|
38
44
|
description?: string;
|
|
39
45
|
source_type?: SkillSourceType;
|
|
@@ -49,10 +55,21 @@ export interface FocusedSkill extends Omit<SkillSummary, "object"> {
|
|
|
49
55
|
manifest?: string;
|
|
50
56
|
manifest_truncated?: boolean;
|
|
51
57
|
entries?: SkillFileEntry[];
|
|
58
|
+
files?: SkillFocusedFile[];
|
|
59
|
+
}
|
|
60
|
+
export interface SkillFocusedFile {
|
|
61
|
+
path: string;
|
|
62
|
+
content?: string;
|
|
63
|
+
truncated?: boolean;
|
|
64
|
+
size?: number;
|
|
65
|
+
branch?: SkillBranch;
|
|
66
|
+
error?: SkillOperationError;
|
|
52
67
|
}
|
|
53
68
|
export interface SkillFocusItem {
|
|
54
69
|
skill_id?: string;
|
|
55
70
|
branch?: SkillBranch;
|
|
71
|
+
paths?: string[];
|
|
72
|
+
include_manifest?: boolean;
|
|
56
73
|
local_skill?: LocalSkillDescriptor;
|
|
57
74
|
}
|
|
58
75
|
export interface SkillOperationError {
|
|
@@ -61,6 +78,7 @@ export interface SkillOperationError {
|
|
|
61
78
|
}
|
|
62
79
|
export interface SkillFocusResultItem {
|
|
63
80
|
ok: boolean;
|
|
81
|
+
skill_ref?: string;
|
|
64
82
|
skill_id?: string;
|
|
65
83
|
local_skill_id?: string;
|
|
66
84
|
branch?: SkillBranch;
|
|
@@ -102,7 +120,8 @@ export interface DiscoverSkillsParams {
|
|
|
102
120
|
export interface FocusSkillParams {
|
|
103
121
|
skills: SkillFocusItem[];
|
|
104
122
|
fallback_to_main?: boolean;
|
|
105
|
-
|
|
123
|
+
max_manifest_chars?: number;
|
|
124
|
+
max_file_chars?: number;
|
|
106
125
|
}
|
|
107
126
|
export interface SkillFileMutation {
|
|
108
127
|
path: string;
|
|
@@ -164,6 +183,69 @@ export interface SkillFile {
|
|
|
164
183
|
truncated?: boolean;
|
|
165
184
|
recursive?: boolean;
|
|
166
185
|
}
|
|
186
|
+
export interface SkillArchiveParams {
|
|
187
|
+
path?: string;
|
|
188
|
+
branch?: SkillBranch;
|
|
189
|
+
fallback_to_main?: boolean;
|
|
190
|
+
}
|
|
191
|
+
export interface SkillArchive {
|
|
192
|
+
path: string;
|
|
193
|
+
content: ArrayBuffer;
|
|
194
|
+
content_type?: string;
|
|
195
|
+
}
|
|
196
|
+
export interface ImportSkillArchiveParams {
|
|
197
|
+
path?: string;
|
|
198
|
+
branch?: SkillBranch;
|
|
199
|
+
replace?: boolean;
|
|
200
|
+
strip_top_level_dir?: boolean;
|
|
201
|
+
}
|
|
202
|
+
export interface SkillImportResponse {
|
|
203
|
+
object: "skill_import_result";
|
|
204
|
+
branch: SkillBranch;
|
|
205
|
+
file_count: number;
|
|
206
|
+
byte_count: number;
|
|
207
|
+
skill: Skill;
|
|
208
|
+
}
|
|
209
|
+
export interface SkillBranchDiffParams {
|
|
210
|
+
path?: string;
|
|
211
|
+
max_file_chars?: number;
|
|
212
|
+
include_unchanged?: boolean;
|
|
213
|
+
}
|
|
214
|
+
export interface SkillBranchDiffFile {
|
|
215
|
+
path: string;
|
|
216
|
+
status: SkillBranchDiffStatus;
|
|
217
|
+
base_size?: number;
|
|
218
|
+
compare_size?: number;
|
|
219
|
+
text?: boolean;
|
|
220
|
+
binary?: boolean;
|
|
221
|
+
too_large?: boolean;
|
|
222
|
+
truncated?: boolean;
|
|
223
|
+
diff?: string;
|
|
224
|
+
}
|
|
225
|
+
export interface SkillBranchDiff {
|
|
226
|
+
object: "skill_branch_diff";
|
|
227
|
+
skill_id: string;
|
|
228
|
+
base_branch: SkillBranch;
|
|
229
|
+
compare_branch: SkillBranch;
|
|
230
|
+
path?: string;
|
|
231
|
+
summary: {
|
|
232
|
+
added: number;
|
|
233
|
+
modified: number;
|
|
234
|
+
deleted: number;
|
|
235
|
+
unchanged: number;
|
|
236
|
+
};
|
|
237
|
+
files: SkillBranchDiffFile[];
|
|
238
|
+
}
|
|
239
|
+
export interface PushSkillDirectoryParams extends ImportSkillArchiveParams {
|
|
240
|
+
}
|
|
241
|
+
export interface PullSkillDirectoryParams extends SkillArchiveParams {
|
|
242
|
+
replace?: boolean;
|
|
243
|
+
}
|
|
244
|
+
export interface SkillDirectoryPullResult {
|
|
245
|
+
path: string;
|
|
246
|
+
file_count: number;
|
|
247
|
+
byte_count: number;
|
|
248
|
+
}
|
|
167
249
|
export interface CreateSkillParams {
|
|
168
250
|
name?: string;
|
|
169
251
|
description?: string;
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "1.0.
|
|
2
|
-
export declare const USER_AGENT = "@agent-api/sdk/1.0.
|
|
1
|
+
export declare const VERSION = "1.0.8";
|
|
2
|
+
export declare const USER_AGENT = "@agent-api/sdk/1.0.8";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const VERSION = "1.0.
|
|
1
|
+
export const VERSION = "1.0.8";
|
|
2
2
|
export const USER_AGENT = `@agent-api/sdk/${VERSION}`;
|