@agent-api/sdk 1.1.3 → 1.1.4
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/README.md +12 -3
- package/dist/client.d.ts +3 -1
- package/dist/client.js +4 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.js +0 -2
- package/dist/node-client.d.ts +6 -0
- package/dist/node-client.js +7 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.js +6 -0
- package/dist/resources/skills-node.d.ts +7 -0
- package/dist/resources/skills-node.js +156 -0
- package/dist/resources/skills.d.ts +1 -3
- package/dist/resources/skills.js +0 -153
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/dist-cjs/client.js +71 -0
- package/dist-cjs/errors.js +146 -0
- package/dist-cjs/index.js +51 -0
- package/dist-cjs/internal/env.js +7 -0
- package/dist-cjs/internal/http.js +108 -0
- package/dist-cjs/internal/output-text.js +15 -0
- package/dist-cjs/internal/query.js +13 -0
- package/dist-cjs/local/context.js +158 -0
- package/dist-cjs/local/core.js +1077 -0
- package/dist-cjs/local/index.js +19 -0
- package/dist-cjs/local/tools.js +380 -0
- package/dist-cjs/local-functions.js +37 -0
- package/dist-cjs/local-skills.js +296 -0
- package/dist-cjs/node-client.js +11 -0
- package/dist-cjs/node.js +32 -0
- package/dist-cjs/package.json +3 -0
- package/dist-cjs/pagination.js +43 -0
- package/dist-cjs/preset-tools.js +91 -0
- package/dist-cjs/resources/auth.js +92 -0
- package/dist-cjs/resources/models.js +13 -0
- package/dist-cjs/resources/presets.js +13 -0
- package/dist-cjs/resources/responses.js +58 -0
- package/dist-cjs/resources/skills-node.js +193 -0
- package/dist-cjs/resources/skills.js +112 -0
- package/dist-cjs/resources/tools.js +13 -0
- package/dist-cjs/resources/volumes.js +114 -0
- package/dist-cjs/streaming.js +42 -0
- package/dist-cjs/tool-validation.js +18 -0
- package/dist-cjs/types/auth.js +2 -0
- package/dist-cjs/types/catalog.js +2 -0
- package/dist-cjs/types/common.js +2 -0
- package/dist-cjs/types/index.js +25 -0
- package/dist-cjs/types/input.js +2 -0
- package/dist-cjs/types/responses.js +2 -0
- package/dist-cjs/types/skills.js +2 -0
- package/dist-cjs/types/streaming.js +2 -0
- package/dist-cjs/types/tools.js +2 -0
- package/dist-cjs/types/volumes.js +2 -0
- package/dist-cjs/version.js +5 -0
- package/package.json +20 -5
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InternalServerError = exports.RateLimitError = exports.BadRequestError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.APIStatusError = exports.APIConnectionError = exports.APIError = void 0;
|
|
4
|
+
exports.requestIDFromHeaders = requestIDFromHeaders;
|
|
5
|
+
exports.retryAfterMsFromHeaders = retryAfterMsFromHeaders;
|
|
6
|
+
exports.parseResponseError = parseResponseError;
|
|
7
|
+
exports.isRetryableStatus = isRetryableStatus;
|
|
8
|
+
class APIError extends Error {
|
|
9
|
+
status;
|
|
10
|
+
headers;
|
|
11
|
+
body;
|
|
12
|
+
code;
|
|
13
|
+
errorType;
|
|
14
|
+
requestID;
|
|
15
|
+
constructor(message, options = {}) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "APIError";
|
|
18
|
+
this.status = options.status;
|
|
19
|
+
this.headers = options.headers;
|
|
20
|
+
this.body = options.body;
|
|
21
|
+
this.code = options.code;
|
|
22
|
+
this.errorType = options.errorType;
|
|
23
|
+
this.requestID = options.requestID;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.APIError = APIError;
|
|
27
|
+
class APIConnectionError extends APIError {
|
|
28
|
+
constructor(message, cause) {
|
|
29
|
+
super(message, { body: cause });
|
|
30
|
+
this.name = "APIConnectionError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.APIConnectionError = APIConnectionError;
|
|
34
|
+
class APIStatusError extends APIError {
|
|
35
|
+
status;
|
|
36
|
+
constructor(message, status, headers, body, options = {}) {
|
|
37
|
+
super(message, { status, headers, body, ...options });
|
|
38
|
+
this.name = "APIStatusError";
|
|
39
|
+
this.status = status;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.APIStatusError = APIStatusError;
|
|
43
|
+
class AuthenticationError extends APIStatusError {
|
|
44
|
+
constructor(message, status, headers, body, options = {}) {
|
|
45
|
+
super(message, status, headers, body, options);
|
|
46
|
+
this.name = "AuthenticationError";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.AuthenticationError = AuthenticationError;
|
|
50
|
+
class PermissionDeniedError extends APIStatusError {
|
|
51
|
+
constructor(message, status, headers, body, options = {}) {
|
|
52
|
+
super(message, status, headers, body, options);
|
|
53
|
+
this.name = "PermissionDeniedError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.PermissionDeniedError = PermissionDeniedError;
|
|
57
|
+
class NotFoundError extends APIStatusError {
|
|
58
|
+
constructor(message, status, headers, body, options = {}) {
|
|
59
|
+
super(message, status, headers, body, options);
|
|
60
|
+
this.name = "NotFoundError";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.NotFoundError = NotFoundError;
|
|
64
|
+
class BadRequestError extends APIStatusError {
|
|
65
|
+
constructor(message, status, headers, body, options = {}) {
|
|
66
|
+
super(message, status, headers, body, options);
|
|
67
|
+
this.name = "BadRequestError";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.BadRequestError = BadRequestError;
|
|
71
|
+
class RateLimitError extends APIStatusError {
|
|
72
|
+
retryAfterMs;
|
|
73
|
+
constructor(message, status, headers, body, retryAfterMs, options = {}) {
|
|
74
|
+
super(message, status, headers, body, options);
|
|
75
|
+
this.name = "RateLimitError";
|
|
76
|
+
this.retryAfterMs = retryAfterMs;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.RateLimitError = RateLimitError;
|
|
80
|
+
class InternalServerError extends APIStatusError {
|
|
81
|
+
constructor(message, status, headers, body, options = {}) {
|
|
82
|
+
super(message, status, headers, body, options);
|
|
83
|
+
this.name = "InternalServerError";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.InternalServerError = InternalServerError;
|
|
87
|
+
function requestIDFromHeaders(headers) {
|
|
88
|
+
return headers.get("x-request-id") ?? headers.get("request-id") ?? undefined;
|
|
89
|
+
}
|
|
90
|
+
function retryAfterMsFromHeaders(headers) {
|
|
91
|
+
const raw = headers.get("retry-after");
|
|
92
|
+
if (!raw) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
const seconds = Number(raw);
|
|
96
|
+
if (Number.isFinite(seconds)) {
|
|
97
|
+
return Math.max(0, seconds * 1000);
|
|
98
|
+
}
|
|
99
|
+
const date = Date.parse(raw);
|
|
100
|
+
if (Number.isFinite(date)) {
|
|
101
|
+
return Math.max(0, date - Date.now());
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
function errorFields(body) {
|
|
106
|
+
if (typeof body === "object" && body !== null && "error" in body) {
|
|
107
|
+
const err = body.error;
|
|
108
|
+
if (err && typeof err.message === "string") {
|
|
109
|
+
return { message: err.message, code: err.code, errorType: err.type };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { message: "" };
|
|
113
|
+
}
|
|
114
|
+
async function parseResponseError(response) {
|
|
115
|
+
let body;
|
|
116
|
+
try {
|
|
117
|
+
body = await response.json();
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
body = await response.text().catch(() => "");
|
|
121
|
+
}
|
|
122
|
+
const { message, code, errorType } = errorFields(body);
|
|
123
|
+
const requestID = requestIDFromHeaders(response.headers);
|
|
124
|
+
const finalMessage = message || `API request failed with status ${response.status}`;
|
|
125
|
+
const common = { code, errorType, requestID };
|
|
126
|
+
switch (response.status) {
|
|
127
|
+
case 400:
|
|
128
|
+
return new BadRequestError(finalMessage, response.status, response.headers, body, common);
|
|
129
|
+
case 401:
|
|
130
|
+
return new AuthenticationError(finalMessage, response.status, response.headers, body, common);
|
|
131
|
+
case 403:
|
|
132
|
+
return new PermissionDeniedError(finalMessage, response.status, response.headers, body, common);
|
|
133
|
+
case 404:
|
|
134
|
+
return new NotFoundError(finalMessage, response.status, response.headers, body, common);
|
|
135
|
+
case 429:
|
|
136
|
+
return new RateLimitError(finalMessage, response.status, response.headers, body, retryAfterMsFromHeaders(response.headers), common);
|
|
137
|
+
default:
|
|
138
|
+
if (response.status >= 500) {
|
|
139
|
+
return new InternalServerError(finalMessage, response.status, response.headers, body, common);
|
|
140
|
+
}
|
|
141
|
+
return new APIStatusError(finalMessage, response.status, response.headers, body, common);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function isRetryableStatus(status) {
|
|
145
|
+
return status === 408 || status === 409 || status === 429 || status === 500 || status === 502 || status === 503 || status === 504;
|
|
146
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.DeviceAuthFlowError = exports.AuthResource = exports.resolvePresetToolsFromCatalog = exports.resolvePresetTools = exports.publicToolToRequestTool = exports.mergeTools = exports.runLocalFunctionHandlers = exports.pendingFunctionCalls = exports.functionCallOutputInput = exports.parseResponseError = exports.isRetryableStatus = exports.RateLimitError = exports.PermissionDeniedError = exports.NotFoundError = exports.InternalServerError = exports.BadRequestError = exports.AuthenticationError = exports.APIStatusError = exports.APIConnectionError = exports.APIError = exports.collectPage = exports.Page = exports.VERSION = exports.DEFAULT_TIMEOUT_MS = exports.DEFAULT_STREAM_TIMEOUT_MS = exports.DEFAULT_MAX_RETRIES = exports.AgentAPI = void 0;
|
|
18
|
+
var client_js_1 = require("./client.js");
|
|
19
|
+
Object.defineProperty(exports, "AgentAPI", { enumerable: true, get: function () { return client_js_1.AgentAPI; } });
|
|
20
|
+
Object.defineProperty(exports, "DEFAULT_MAX_RETRIES", { enumerable: true, get: function () { return client_js_1.DEFAULT_MAX_RETRIES; } });
|
|
21
|
+
Object.defineProperty(exports, "DEFAULT_STREAM_TIMEOUT_MS", { enumerable: true, get: function () { return client_js_1.DEFAULT_STREAM_TIMEOUT_MS; } });
|
|
22
|
+
Object.defineProperty(exports, "DEFAULT_TIMEOUT_MS", { enumerable: true, get: function () { return client_js_1.DEFAULT_TIMEOUT_MS; } });
|
|
23
|
+
Object.defineProperty(exports, "VERSION", { enumerable: true, get: function () { return client_js_1.VERSION; } });
|
|
24
|
+
var pagination_js_1 = require("./pagination.js");
|
|
25
|
+
Object.defineProperty(exports, "Page", { enumerable: true, get: function () { return pagination_js_1.Page; } });
|
|
26
|
+
Object.defineProperty(exports, "collectPage", { enumerable: true, get: function () { return pagination_js_1.collectPage; } });
|
|
27
|
+
var errors_js_1 = require("./errors.js");
|
|
28
|
+
Object.defineProperty(exports, "APIError", { enumerable: true, get: function () { return errors_js_1.APIError; } });
|
|
29
|
+
Object.defineProperty(exports, "APIConnectionError", { enumerable: true, get: function () { return errors_js_1.APIConnectionError; } });
|
|
30
|
+
Object.defineProperty(exports, "APIStatusError", { enumerable: true, get: function () { return errors_js_1.APIStatusError; } });
|
|
31
|
+
Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_js_1.AuthenticationError; } });
|
|
32
|
+
Object.defineProperty(exports, "BadRequestError", { enumerable: true, get: function () { return errors_js_1.BadRequestError; } });
|
|
33
|
+
Object.defineProperty(exports, "InternalServerError", { enumerable: true, get: function () { return errors_js_1.InternalServerError; } });
|
|
34
|
+
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return errors_js_1.NotFoundError; } });
|
|
35
|
+
Object.defineProperty(exports, "PermissionDeniedError", { enumerable: true, get: function () { return errors_js_1.PermissionDeniedError; } });
|
|
36
|
+
Object.defineProperty(exports, "RateLimitError", { enumerable: true, get: function () { return errors_js_1.RateLimitError; } });
|
|
37
|
+
Object.defineProperty(exports, "isRetryableStatus", { enumerable: true, get: function () { return errors_js_1.isRetryableStatus; } });
|
|
38
|
+
Object.defineProperty(exports, "parseResponseError", { enumerable: true, get: function () { return errors_js_1.parseResponseError; } });
|
|
39
|
+
__exportStar(require("./types/index.js"), exports);
|
|
40
|
+
var local_functions_js_1 = require("./local-functions.js");
|
|
41
|
+
Object.defineProperty(exports, "functionCallOutputInput", { enumerable: true, get: function () { return local_functions_js_1.functionCallOutputInput; } });
|
|
42
|
+
Object.defineProperty(exports, "pendingFunctionCalls", { enumerable: true, get: function () { return local_functions_js_1.pendingFunctionCalls; } });
|
|
43
|
+
Object.defineProperty(exports, "runLocalFunctionHandlers", { enumerable: true, get: function () { return local_functions_js_1.runLocalFunctionHandlers; } });
|
|
44
|
+
var preset_tools_js_1 = require("./preset-tools.js");
|
|
45
|
+
Object.defineProperty(exports, "mergeTools", { enumerable: true, get: function () { return preset_tools_js_1.mergeTools; } });
|
|
46
|
+
Object.defineProperty(exports, "publicToolToRequestTool", { enumerable: true, get: function () { return preset_tools_js_1.publicToolToRequestTool; } });
|
|
47
|
+
Object.defineProperty(exports, "resolvePresetTools", { enumerable: true, get: function () { return preset_tools_js_1.resolvePresetTools; } });
|
|
48
|
+
Object.defineProperty(exports, "resolvePresetToolsFromCatalog", { enumerable: true, get: function () { return preset_tools_js_1.resolvePresetToolsFromCatalog; } });
|
|
49
|
+
var auth_js_1 = require("./resources/auth.js");
|
|
50
|
+
Object.defineProperty(exports, "AuthResource", { enumerable: true, get: function () { return auth_js_1.AuthResource; } });
|
|
51
|
+
Object.defineProperty(exports, "DeviceAuthFlowError", { enumerable: true, get: function () { return auth_js_1.DeviceAuthFlowError; } });
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HTTPClient = void 0;
|
|
4
|
+
const errors_js_1 = require("../errors.js");
|
|
5
|
+
const streaming_js_1 = require("../streaming.js");
|
|
6
|
+
const version_js_1 = require("../version.js");
|
|
7
|
+
class HTTPClient {
|
|
8
|
+
options;
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
}
|
|
12
|
+
async request(method, path, body, options = {}) {
|
|
13
|
+
const response = await this.fetchWithRetry(method, path, body, options, false, false);
|
|
14
|
+
return (await response.json());
|
|
15
|
+
}
|
|
16
|
+
async requestRaw(method, path, body, options = {}) {
|
|
17
|
+
const response = await this.fetchWithRetry(method, path, body, options, false, true);
|
|
18
|
+
return (await response.json());
|
|
19
|
+
}
|
|
20
|
+
async requestVoid(method, path, options = {}) {
|
|
21
|
+
await this.fetchWithRetry(method, path, undefined, options, false, false);
|
|
22
|
+
}
|
|
23
|
+
async requestBinary(method, path, options = {}) {
|
|
24
|
+
const response = await this.fetchWithRetry(method, path, undefined, options, false, false);
|
|
25
|
+
return { body: await response.arrayBuffer(), headers: response.headers };
|
|
26
|
+
}
|
|
27
|
+
async stream(path, body, options = {}) {
|
|
28
|
+
const response = await this.fetchWithRetry("POST", path, body, options, true, false);
|
|
29
|
+
return (0, streaming_js_1.parseSSE)(response);
|
|
30
|
+
}
|
|
31
|
+
async fetchWithRetry(method, path, body, options, stream, rawBody) {
|
|
32
|
+
const maxRetries = options.maxRetries ?? this.options.maxRetries;
|
|
33
|
+
let attempt = 0;
|
|
34
|
+
for (;;) {
|
|
35
|
+
try {
|
|
36
|
+
return await this.fetchOnce(method, path, body, options, stream, rawBody);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (!(error instanceof errors_js_1.APIError) || attempt >= maxRetries) {
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
const retryable = error instanceof errors_js_1.APIConnectionError ||
|
|
43
|
+
(error.status !== undefined && (0, errors_js_1.isRetryableStatus)(error.status));
|
|
44
|
+
if (!retryable) {
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
attempt += 1;
|
|
48
|
+
const delayMs = retryDelayMs(error, attempt);
|
|
49
|
+
await sleep(delayMs);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async fetchOnce(method, path, body, options, stream, rawBody) {
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
const timeout = options.timeout ?? (stream ? this.options.streamTimeout : this.options.timeout);
|
|
56
|
+
const timeoutID = setTimeout(() => controller.abort(), timeout);
|
|
57
|
+
try {
|
|
58
|
+
const headers = {
|
|
59
|
+
Accept: stream ? "text/event-stream" : "application/json",
|
|
60
|
+
"User-Agent": version_js_1.USER_AGENT,
|
|
61
|
+
...this.options.defaultHeaders,
|
|
62
|
+
...options.headers,
|
|
63
|
+
};
|
|
64
|
+
if (body !== undefined && !rawBody) {
|
|
65
|
+
headers["Content-Type"] = "application/json";
|
|
66
|
+
}
|
|
67
|
+
if (this.options.apiKey) {
|
|
68
|
+
headers.Authorization = `Bearer ${this.options.apiKey}`;
|
|
69
|
+
}
|
|
70
|
+
const response = await this.options.fetchImpl(`${this.options.baseURL}${path}`, {
|
|
71
|
+
method,
|
|
72
|
+
headers,
|
|
73
|
+
body: body === undefined ? undefined : rawBody ? body : JSON.stringify(body),
|
|
74
|
+
signal: controller.signal,
|
|
75
|
+
});
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
throw await (0, errors_js_1.parseResponseError)(response);
|
|
78
|
+
}
|
|
79
|
+
return response;
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
if (error instanceof errors_js_1.APIError) {
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
86
|
+
throw new errors_js_1.APIConnectionError(`Request timed out after ${timeout}ms`, error);
|
|
87
|
+
}
|
|
88
|
+
throw new errors_js_1.APIConnectionError("Request failed", error);
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
clearTimeout(timeoutID);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.HTTPClient = HTTPClient;
|
|
96
|
+
function retryDelayMs(error, attempt) {
|
|
97
|
+
if (error instanceof errors_js_1.RateLimitError && error.retryAfterMs !== undefined) {
|
|
98
|
+
return error.retryAfterMs;
|
|
99
|
+
}
|
|
100
|
+
const base = 250;
|
|
101
|
+
const cap = 8000;
|
|
102
|
+
const exponential = Math.min(cap, base * 2 ** (attempt - 1));
|
|
103
|
+
const jitter = Math.floor(Math.random() * 100);
|
|
104
|
+
return exponential + jitter;
|
|
105
|
+
}
|
|
106
|
+
function sleep(ms) {
|
|
107
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
108
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addOutputText = addOutputText;
|
|
4
|
+
function addOutputText(response) {
|
|
5
|
+
if (response.output_text !== undefined) {
|
|
6
|
+
return response;
|
|
7
|
+
}
|
|
8
|
+
response.output_text = response.output
|
|
9
|
+
.filter((item) => item.type === "message")
|
|
10
|
+
.flatMap((item) => item.content)
|
|
11
|
+
.filter((part) => part.type === "output_text")
|
|
12
|
+
.map((part) => part.text ?? "")
|
|
13
|
+
.join("");
|
|
14
|
+
return response;
|
|
15
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildQuery = buildQuery;
|
|
4
|
+
function buildQuery(params) {
|
|
5
|
+
const search = new URLSearchParams();
|
|
6
|
+
for (const [key, value] of Object.entries(params)) {
|
|
7
|
+
if (value !== undefined && value !== "") {
|
|
8
|
+
search.set(key, String(value));
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const qs = search.toString();
|
|
12
|
+
return qs ? `?${qs}` : "";
|
|
13
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createLocalContextPackage = createLocalContextPackage;
|
|
4
|
+
exports.summarizeLocalContextSensitivity = summarizeLocalContextSensitivity;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const core_js_1 = require("./core.js");
|
|
8
|
+
async function createLocalContextPackage(workspace, params = {}) {
|
|
9
|
+
const basePath = params.path ?? ".";
|
|
10
|
+
const maxFiles = positiveInt(params.maxFiles, 80);
|
|
11
|
+
const maxBytes = positiveInt(params.maxBytes, 256 * 1024);
|
|
12
|
+
const maxBytesPerFile = positiveInt(params.maxBytesPerFile, 32 * 1024);
|
|
13
|
+
const previewBytes = positiveInt(params.previewBytes, maxBytesPerFile);
|
|
14
|
+
const includeContent = params.includeContent ?? true;
|
|
15
|
+
const includeHashes = params.includeHashes ?? true;
|
|
16
|
+
const includeSummary = params.includeSummary ?? true;
|
|
17
|
+
const includeSearch = Boolean(params.includeSearch && params.query?.trim());
|
|
18
|
+
const includeSecrets = params.includeSecrets ?? false;
|
|
19
|
+
const stats = await workspace.list(basePath, { recursive: true });
|
|
20
|
+
const fileStats = stats
|
|
21
|
+
.filter((item) => item.type === "file")
|
|
22
|
+
.filter((item) => matchesPathFilters(item.path, params.include, params.exclude))
|
|
23
|
+
.sort((a, b) => a.path.localeCompare(b.path));
|
|
24
|
+
const files = [];
|
|
25
|
+
let includedBytes = 0;
|
|
26
|
+
let truncated = fileStats.length > maxFiles;
|
|
27
|
+
for (const item of fileStats.slice(0, maxFiles)) {
|
|
28
|
+
const sensitivity = (0, core_js_1.classifyLocalPathSensitivity)(item.path);
|
|
29
|
+
const baseFile = {
|
|
30
|
+
path: item.path,
|
|
31
|
+
size: item.size,
|
|
32
|
+
sensitivity: sensitivity.sensitivity,
|
|
33
|
+
sensitivity_reason: sensitivity.reason,
|
|
34
|
+
};
|
|
35
|
+
if (!includeSecrets && sensitivity.sensitivity === "secret") {
|
|
36
|
+
files.push({ ...baseFile, omitted_reason: "secret_path" });
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (item.size > maxBytesPerFile) {
|
|
40
|
+
files.push({ ...baseFile, omitted_reason: "file_too_large" });
|
|
41
|
+
truncated = true;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (includedBytes >= maxBytes) {
|
|
45
|
+
files.push({ ...baseFile, omitted_reason: "package_budget_exceeded" });
|
|
46
|
+
truncated = true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const remaining = maxBytes - includedBytes;
|
|
50
|
+
const readBudget = Math.min(previewBytes, maxBytesPerFile, remaining);
|
|
51
|
+
if (readBudget <= 0) {
|
|
52
|
+
files.push({ ...baseFile, omitted_reason: "package_budget_exceeded" });
|
|
53
|
+
truncated = true;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const delivered = await workspace.readFile(item.path, { maxBytes: readBudget });
|
|
57
|
+
includedBytes += delivered.encoding === "text"
|
|
58
|
+
? Buffer.byteLength(delivered.content ?? "", "utf8")
|
|
59
|
+
: Buffer.byteLength(delivered.content_base64 ?? "", "base64");
|
|
60
|
+
const packaged = {
|
|
61
|
+
...baseFile,
|
|
62
|
+
mime_type: delivered.mime_type,
|
|
63
|
+
encoding: delivered.encoding,
|
|
64
|
+
truncated: delivered.truncated || undefined,
|
|
65
|
+
};
|
|
66
|
+
if (includeContent) {
|
|
67
|
+
packaged.content = delivered.content;
|
|
68
|
+
packaged.content_base64 = delivered.content_base64;
|
|
69
|
+
}
|
|
70
|
+
if (includeHashes) {
|
|
71
|
+
packaged.sha256 = await sha256File(workspace, item.path);
|
|
72
|
+
}
|
|
73
|
+
if (delivered.truncated) {
|
|
74
|
+
truncated = true;
|
|
75
|
+
}
|
|
76
|
+
files.push(packaged);
|
|
77
|
+
}
|
|
78
|
+
const summary = includeSummary
|
|
79
|
+
? await workspace.summarize({
|
|
80
|
+
path: basePath,
|
|
81
|
+
maxFiles,
|
|
82
|
+
previewBytes,
|
|
83
|
+
ignore: params.exclude,
|
|
84
|
+
})
|
|
85
|
+
: undefined;
|
|
86
|
+
const search = includeSearch
|
|
87
|
+
? await workspace.grep({
|
|
88
|
+
pattern: params.query,
|
|
89
|
+
path: basePath,
|
|
90
|
+
limit: maxFiles,
|
|
91
|
+
maxBytesPerFile,
|
|
92
|
+
ignore: params.exclude,
|
|
93
|
+
})
|
|
94
|
+
: undefined;
|
|
95
|
+
return {
|
|
96
|
+
object: "local_context_manifest",
|
|
97
|
+
root: workspace.root,
|
|
98
|
+
workspace_name: workspace.name,
|
|
99
|
+
generated_at_unix: Math.floor(Date.now() / 1000),
|
|
100
|
+
base_path: basePath,
|
|
101
|
+
file_count: fileStats.length,
|
|
102
|
+
total_bytes: fileStats.reduce((sum, item) => sum + item.size, 0),
|
|
103
|
+
included_bytes: includedBytes,
|
|
104
|
+
truncated,
|
|
105
|
+
files,
|
|
106
|
+
summary,
|
|
107
|
+
search,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function summarizeLocalContextSensitivity(files) {
|
|
111
|
+
const order = { normal: 0, sensitive: 1, secret: 2 };
|
|
112
|
+
let highest = "normal";
|
|
113
|
+
const sensitiveFiles = [];
|
|
114
|
+
for (const file of files) {
|
|
115
|
+
if (order[file.sensitivity] > order[highest]) {
|
|
116
|
+
highest = file.sensitivity;
|
|
117
|
+
}
|
|
118
|
+
if (file.sensitivity !== "normal") {
|
|
119
|
+
sensitiveFiles.push({
|
|
120
|
+
path: file.path,
|
|
121
|
+
sensitivity: file.sensitivity,
|
|
122
|
+
reason: file.sensitivity_reason,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { highest, files: sensitiveFiles };
|
|
127
|
+
}
|
|
128
|
+
function matchesPathFilters(relativePath, include, exclude) {
|
|
129
|
+
if (include?.length && !include.some((pattern) => pathMatches(relativePath, pattern))) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (exclude?.some((pattern) => pathMatches(relativePath, pattern))) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
function pathMatches(relativePath, pattern) {
|
|
138
|
+
const clean = pattern.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
139
|
+
if (!clean || clean === ".") {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
if (!clean.includes("*")) {
|
|
143
|
+
return relativePath === clean || relativePath.startsWith(`${clean}/`);
|
|
144
|
+
}
|
|
145
|
+
const escaped = clean
|
|
146
|
+
.split("*")
|
|
147
|
+
.map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&"))
|
|
148
|
+
.join(".*");
|
|
149
|
+
return new RegExp(`^${escaped}$`).test(relativePath);
|
|
150
|
+
}
|
|
151
|
+
function positiveInt(value, fallback) {
|
|
152
|
+
const parsed = Number(value);
|
|
153
|
+
return Number.isFinite(parsed) && parsed > 0 ? Math.trunc(parsed) : fallback;
|
|
154
|
+
}
|
|
155
|
+
async function sha256File(workspace, relativePath) {
|
|
156
|
+
const fullPath = workspace.files.resolvePath(relativePath);
|
|
157
|
+
return (0, node_crypto_1.createHash)("sha256").update(await (0, promises_1.readFile)(fullPath)).digest("hex");
|
|
158
|
+
}
|