@theokit/sdk-tools 0.27.5 → 0.28.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.
- package/CHANGELOG.md +59 -0
- package/dist/extract-document.cjs +175 -0
- package/dist/extract-document.cjs.map +1 -0
- package/dist/extract-document.d.cts +59 -0
- package/dist/extract-document.d.ts +59 -0
- package/dist/extract-document.js +173 -0
- package/dist/extract-document.js.map +1 -0
- package/dist/github-link-preview.cjs +227 -0
- package/dist/github-link-preview.cjs.map +1 -0
- package/dist/github-link-preview.d.cts +69 -0
- package/dist/github-link-preview.d.ts +69 -0
- package/dist/github-link-preview.js +225 -0
- package/dist/github-link-preview.js.map +1 -0
- package/dist/index.cjs +127 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -1
- package/dist/index.d.ts +108 -1
- package/dist/index.js +128 -11
- package/dist/index.js.map +1 -1
- package/dist/read-pdf.cjs +154 -0
- package/dist/read-pdf.cjs.map +1 -0
- package/dist/read-pdf.d.cts +58 -0
- package/dist/read-pdf.d.ts +58 -0
- package/dist/read-pdf.js +152 -0
- package/dist/read-pdf.js.map +1 -0
- package/dist/screenshot-logbook.cjs +245 -0
- package/dist/screenshot-logbook.cjs.map +1 -0
- package/dist/screenshot-logbook.d.cts +124 -0
- package/dist/screenshot-logbook.d.ts +124 -0
- package/dist/screenshot-logbook.js +241 -0
- package/dist/screenshot-logbook.js.map +1 -0
- package/package.json +55 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/github-link-preview.ts"],"names":[],"mappings":"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","file":"github-link-preview.js","sourcesContent":["/**\n * `github_link_preview` — turn a github.com issue, pull request or repository URL into its title,\n * state and summary.\n *\n * The model's URL is parsed, never fetched: owner, repository and number are validated against\n * GitHub's own name charset and the request always goes to a fixed `https://api.github.com`\n * endpoint built from those parts (ADR D1). Redirects are refused, so a response can never choose\n * the next host or carry the bearer token elsewhere (ADR D2).\n *\n * Return shape (always a JSON string):\n * - `{ ok: true, kind, url, title, state, summary }`\n * - `{ ok: false, error: 'unsupported_url' | 'redirect_blocked' | 'not_found' | 'rate_limited' |\n * 'upstream_error' | 'timeout' | 'fetch_failed' | 'invalid_response', url, ... }`\n */\n\nimport type { CustomTool } from \"@theokit/sdk\";\n\nimport { Tool } from \"@theokit/sdk\";\nimport { z } from \"zod\";\n\nconst API_BASE = \"https://api.github.com\";\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_SUMMARY_CHARS = 500;\nconst MAX_BODY_BYTES = 1_048_576;\nconst GITHUB_HOSTS = new Set([\"github.com\", \"www.github.com\"]);\nconst OWNER_PATTERN = /^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})$/;\nconst REPO_PATTERN = /^[A-Za-z0-9._-]{1,100}$/;\nconst NUMBER_PATTERN = /^[1-9][0-9]{0,9}$/;\n\n/** What a previewed GitHub URL points at, taken from its path. */\nexport type GithubLinkKind = \"repository\" | \"issue\" | \"pull_request\";\n\n/** Options for {@link createGithubLinkPreviewTool}; every one is optional. */\nexport interface CreateGithubLinkPreviewToolOptions {\n /** Fetch implementation with the global `fetch` signature (injectable for tests). */\n fetchImpl?: typeof fetch;\n /** Optional GitHub token, sent as `Authorization: Bearer` to api.github.com only. */\n token?: string;\n /** Name exposed to the model. Default `github_link_preview`. */\n name?: string;\n /** Description exposed to the model. */\n description?: string;\n /** Timeout covering the request and the body read, in ms. Default 10000. */\n timeoutMs?: number;\n /** Longest summary returned, in code points. Default 500. */\n maxSummaryChars?: number;\n /** Clock for `retry_after_seconds` (injectable for tests). Default `Date.now`. */\n now?: () => number;\n}\n\n/** The JSON the `github_link_preview` tool returns: a preview, or a typed failure. */\nexport type GithubLinkPreviewResult =\n | {\n ok: true;\n kind: GithubLinkKind;\n url: string;\n title: string;\n state: string;\n summary: string;\n }\n | {\n ok: false;\n error:\n | \"unsupported_url\"\n | \"redirect_blocked\"\n | \"not_found\"\n | \"rate_limited\"\n | \"upstream_error\"\n | \"timeout\"\n | \"fetch_failed\"\n | \"invalid_response\";\n url: string;\n status?: number;\n retry_after_seconds?: number;\n timeout_ms?: number;\n error_name?: string;\n };\n\ninterface GithubTarget {\n kind: GithubLinkKind;\n owner: string;\n repo: string;\n number?: string;\n}\n\ninterface Settings {\n fetchImpl: typeof fetch;\n headers: Record<string, string>;\n timeoutMs: number;\n maxSummaryChars: number;\n now: () => number;\n}\n\ntype Failure = Extract<GithubLinkPreviewResult, { ok: false }>;\ntype FailureError = Failure[\"error\"];\n\nclass PreviewFailure extends Error {\n constructor(\n readonly error: FailureError,\n readonly extra: Omit<Failure, \"ok\" | \"error\" | \"url\"> = {},\n ) {\n super(error);\n }\n}\n\nfunction requirePositiveInteger(name: string, value: number): number {\n if (!Number.isInteger(value) || value <= 0) {\n throw new RangeError(\n `createGithubLinkPreviewTool: ${name} must be a positive integer, got ${value}`,\n );\n }\n return value;\n}\n\nfunction hasControlCharacter(text: string): boolean {\n return Array.from(text).some((char) => {\n const code = char.charCodeAt(0);\n return code < 0x20 || code === 0x7f;\n });\n}\n\nfunction requireValidToken(token: string): string {\n if (token.trim() === \"\" || hasControlCharacter(token)) {\n throw new RangeError(\n \"createGithubLinkPreviewTool: token must be non-blank and free of control characters\",\n );\n }\n return token;\n}\n\nfunction buildHeaders(token: string | undefined): Record<string, string> {\n const headers: Record<string, string> = {\n accept: \"application/vnd.github+json\",\n \"user-agent\": \"theokit-sdk-tools\",\n \"x-github-api-version\": \"2022-11-28\",\n };\n if (token !== undefined) headers.authorization = `Bearer ${token}`;\n return headers;\n}\n\nfunction isGithubOrigin(parsed: URL): boolean {\n return (\n parsed.protocol === \"https:\" &&\n GITHUB_HOSTS.has(parsed.hostname) &&\n parsed.username === \"\" &&\n parsed.password === \"\" &&\n parsed.port === \"\"\n );\n}\n\nconst SECTION_KINDS: Readonly<Record<string, GithubLinkKind>> = {\n issues: \"issue\",\n pull: \"pull_request\",\n};\n\nfunction isValidRepository(owner: string, repo: string): boolean {\n return OWNER_PATTERN.test(owner) && REPO_PATTERN.test(repo) && repo !== \".\" && repo !== \"..\";\n}\n\nfunction numberedTarget(owner: string, repo: string, segments: string[]): GithubTarget | undefined {\n const [, , section = \"\", number = \"\"] = segments;\n const kind = Object.hasOwn(SECTION_KINDS, section) ? SECTION_KINDS[section] : undefined;\n if (segments.length !== 4 || kind === undefined || !NUMBER_PATTERN.test(number)) return undefined;\n return { kind, owner, repo, number };\n}\n\nfunction targetFromSegments(segments: string[]): GithubTarget | undefined {\n const [owner = \"\", repo = \"\"] = segments;\n if (!isValidRepository(owner, repo)) return undefined;\n if (segments.length === 2) return { kind: \"repository\", owner, repo };\n return numberedTarget(owner, repo, segments);\n}\n\nfunction parseGithubUrl(url: string): GithubTarget | undefined {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n return undefined;\n }\n if (!isGithubOrigin(parsed)) return undefined;\n const segments = parsed.pathname.split(\"/\").slice(1);\n if (segments.at(-1) === \"\") segments.pop();\n return targetFromSegments(segments);\n}\n\nfunction apiUrlFor(target: GithubTarget): string {\n const base = `${API_BASE}/repos/${target.owner}/${target.repo}`;\n if (target.kind === \"issue\") return `${base}/issues/${target.number}`;\n if (target.kind === \"pull_request\") return `${base}/pulls/${target.number}`;\n return base;\n}\n\nfunction canonicalUrlFor(target: GithubTarget): string {\n const base = `https://github.com/${target.owner}/${target.repo}`;\n if (target.kind === \"issue\") return `${base}/issues/${target.number}`;\n if (target.kind === \"pull_request\") return `${base}/pull/${target.number}`;\n return base;\n}\n\n// `retry-after` is read as delta-seconds only; an HTTP-date value falls through to the epoch reset.\nfunction retryAfterSeconds(headers: Headers, nowMs: number): number | undefined {\n const retryAfter = Number(headers.get(\"retry-after\") ?? Number.NaN);\n if (Number.isFinite(retryAfter)) return Math.max(0, Math.ceil(retryAfter));\n const reset = Number(headers.get(\"x-ratelimit-reset\") ?? Number.NaN);\n if (Number.isFinite(reset)) return Math.max(0, Math.ceil(reset - nowMs / 1000));\n return undefined;\n}\n\nfunction isRateLimited(response: Response): boolean {\n if (response.status !== 403 && response.status !== 429) return false;\n return (\n response.headers.get(\"x-ratelimit-remaining\") === \"0\" || response.headers.has(\"retry-after\")\n );\n}\n\nfunction checkStatus(response: Response, nowMs: number): void {\n const { status } = response;\n if (status >= 200 && status < 300) return;\n if (status >= 300 && status < 400) throw new PreviewFailure(\"redirect_blocked\", { status });\n if (status === 404) throw new PreviewFailure(\"not_found\", { status });\n if (isRateLimited(response)) {\n const retry = retryAfterSeconds(response.headers, nowMs);\n throw new PreviewFailure(\"rate_limited\", {\n status,\n ...(retry === undefined ? {} : { retry_after_seconds: retry }),\n });\n }\n throw new PreviewFailure(\"upstream_error\", { status });\n}\n\nasync function readCappedJson(response: Response): Promise<unknown> {\n if (Number(response.headers.get(\"content-length\") ?? 0) > MAX_BODY_BYTES) {\n throw new PreviewFailure(\"invalid_response\");\n }\n const text = await response.text();\n if (Buffer.byteLength(text, \"utf8\") > MAX_BODY_BYTES) {\n throw new PreviewFailure(\"invalid_response\");\n }\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw new PreviewFailure(\"invalid_response\");\n }\n}\n\nfunction cutCodePoints(text: unknown, max: number): string {\n if (typeof text !== \"string\") return \"\";\n return Array.from(text).slice(0, max).join(\"\");\n}\n\nfunction stateOf(target: GithubTarget, body: Record<string, unknown>): string {\n if (target.kind === \"repository\") return body.archived === true ? \"archived\" : \"active\";\n if (target.kind === \"pull_request\" && body.merged === true) return \"merged\";\n if (typeof body.state !== \"string\") throw new PreviewFailure(\"invalid_response\");\n return body.state;\n}\n\nfunction mapPreview(\n target: GithubTarget,\n body: unknown,\n maxSummaryChars: number,\n): GithubLinkPreviewResult {\n if (typeof body !== \"object\" || body === null || Array.isArray(body)) {\n throw new PreviewFailure(\"invalid_response\");\n }\n const record = body as Record<string, unknown>;\n const isRepository = target.kind === \"repository\";\n const title = isRepository ? record.full_name : record.title;\n if (typeof title !== \"string\") throw new PreviewFailure(\"invalid_response\");\n return {\n ok: true,\n kind: target.kind,\n url: canonicalUrlFor(target),\n title,\n state: stateOf(target, record),\n summary: cutCodePoints(isRepository ? record.description : record.body, maxSummaryChars),\n };\n}\n\nfunction failureFor(err: unknown, timeoutMs: number): PreviewFailure {\n if (err instanceof PreviewFailure) return err;\n const name = (err as { name?: unknown } | null)?.name;\n if (name === \"AbortError\" || name === \"TimeoutError\") {\n return new PreviewFailure(\"timeout\", { timeout_ms: timeoutMs });\n }\n return new PreviewFailure(\"fetch_failed\", {\n error_name: typeof name === \"string\" ? name : \"unknown\",\n });\n}\n\nasync function fetchPreview(\n target: GithubTarget,\n settings: Settings,\n): Promise<GithubLinkPreviewResult> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), settings.timeoutMs);\n try {\n const response = await settings.fetchImpl(apiUrlFor(target), {\n method: \"GET\",\n redirect: \"manual\",\n signal: controller.signal,\n headers: settings.headers,\n });\n checkStatus(response, settings.now());\n const body = await readCappedJson(response);\n return mapPreview(target, body, settings.maxSummaryChars);\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function preview(url: string, settings: Settings): Promise<GithubLinkPreviewResult> {\n const target = parseGithubUrl(url);\n if (target === undefined) return { ok: false, error: \"unsupported_url\", url };\n try {\n return await fetchPreview(target, settings);\n } catch (err) {\n const failure = failureFor(err, settings.timeoutMs);\n return { ok: false, error: failure.error, url, ...failure.extra };\n }\n}\n\n/**\n * Build the `github_link_preview` tool. Every option is optional: `createGithubLinkPreviewTool()`\n * previews public objects anonymously with a 10-second timeout and a 500-character summary.\n *\n * Only three URL shapes are accepted: `https://github.com/<owner>/<repo>`,\n * `.../issues/<n>` and `.../pull/<n>` (also on `www.github.com`; a trailing slash, query or\n * fragment is ignored). Anything else is `unsupported_url` and makes no request.\n *\n * Throws `RangeError` at construction for a non-positive or fractional `timeoutMs` or\n * `maxSummaryChars`, and for a blank token or one with a control character. Every failure after\n * construction is a typed `{ ok: false, error }` result, never a throw. The token is never\n * echoed: error bodies are not returned, and `fetch_failed` carries only the error's name.\n */\nexport function createGithubLinkPreviewTool(opts?: CreateGithubLinkPreviewToolOptions): CustomTool {\n const settings: Settings = {\n fetchImpl: opts?.fetchImpl ?? fetch,\n headers: buildHeaders(opts?.token === undefined ? undefined : requireValidToken(opts.token)),\n timeoutMs: requirePositiveInteger(\"timeoutMs\", opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS),\n maxSummaryChars: requirePositiveInteger(\n \"maxSummaryChars\",\n opts?.maxSummaryChars ?? DEFAULT_MAX_SUMMARY_CHARS,\n ),\n now: opts?.now ?? Date.now,\n };\n\n return Tool.create({\n name: opts?.name ?? \"github_link_preview\",\n description:\n opts?.description ??\n \"Preview a GitHub issue, pull request or repository from its github.com URL. Returns \" +\n \"{ ok, kind, url, title, state, summary } where state is open/closed/merged for issues and \" +\n \"pull requests and active/archived for repositories, or { ok: false, error }. Only \" +\n \"https://github.com/<owner>/<repo>, .../issues/<n> and .../pull/<n> are accepted.\",\n inputSchema: z.object({\n url: z.string().min(1).describe(\"A github.com repository, issue or pull request URL.\"),\n }),\n handler: async ({ url }) => JSON.stringify(await preview(url, settings)),\n });\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -2461,6 +2461,123 @@ function formatResult(result, timeoutMs) {
|
|
|
2461
2461
|
exit_code: result.exitCode
|
|
2462
2462
|
});
|
|
2463
2463
|
}
|
|
2464
|
+
var AUDIO_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
2465
|
+
["audio/mpeg", "mp3"],
|
|
2466
|
+
["audio/wav", "wav"],
|
|
2467
|
+
["audio/x-wav", "wav"],
|
|
2468
|
+
["audio/ogg", "ogg"],
|
|
2469
|
+
["audio/opus", "opus"],
|
|
2470
|
+
["audio/flac", "flac"],
|
|
2471
|
+
["audio/aac", "aac"],
|
|
2472
|
+
["audio/webm", "webm"]
|
|
2473
|
+
]);
|
|
2474
|
+
var DEFAULT_MAX_TEXT_CHARS = 4096;
|
|
2475
|
+
var DEFAULT_MAX_AUDIO_BYTES = 10 * 1024 * 1024;
|
|
2476
|
+
var STEM_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
2477
|
+
var json = (result) => JSON.stringify(result);
|
|
2478
|
+
var errorMessage = (err) => err instanceof Error ? err.message : String(err);
|
|
2479
|
+
var errorCode = (err) => err.code ?? "unknown";
|
|
2480
|
+
function requirePositiveInteger(name, value) {
|
|
2481
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
2482
|
+
throw new RangeError(
|
|
2483
|
+
`createTextToSpeechTool: ${name} must be a positive integer, got ${value}`
|
|
2484
|
+
);
|
|
2485
|
+
}
|
|
2486
|
+
return value;
|
|
2487
|
+
}
|
|
2488
|
+
function defaultStem(text) {
|
|
2489
|
+
return `speech-${crypto.createHash("sha256").update(text).digest("hex").slice(0, 8)}`;
|
|
2490
|
+
}
|
|
2491
|
+
function refusePath(relativeStem, stem, projectRoot) {
|
|
2492
|
+
if (!STEM_PATTERN.test(stem) || isForbiddenAtAnyDepth(relativeStem)) {
|
|
2493
|
+
return json({ ok: false, error: "path_traversal", path: relativeStem });
|
|
2494
|
+
}
|
|
2495
|
+
return checkPathScope(relativeStem, projectRoot);
|
|
2496
|
+
}
|
|
2497
|
+
async function synthesizeSafely(synthesize, text) {
|
|
2498
|
+
try {
|
|
2499
|
+
const value = await synthesize(text);
|
|
2500
|
+
if (!(value?.audio instanceof Uint8Array) || typeof value.mimeType !== "string") {
|
|
2501
|
+
return { ok: false, error: "synthesis_failed", message: "provider returned no audio" };
|
|
2502
|
+
}
|
|
2503
|
+
return { audio: value.audio, mimeType: value.mimeType };
|
|
2504
|
+
} catch (err) {
|
|
2505
|
+
return { ok: false, error: "synthesis_failed", message: errorMessage(err) };
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
function checkAudio({ audio, mimeType }, maxAudioBytes) {
|
|
2509
|
+
const extension = AUDIO_EXTENSIONS.get(mimeType);
|
|
2510
|
+
if (extension === void 0)
|
|
2511
|
+
return { ok: false, error: "unsupported_audio_type", mime_type: mimeType };
|
|
2512
|
+
if (audio.length === 0) return { ok: false, error: "empty_audio" };
|
|
2513
|
+
if (audio.length > maxAudioBytes) {
|
|
2514
|
+
return { ok: false, error: "audio_too_large", bytes: audio.length, max_bytes: maxAudioBytes };
|
|
2515
|
+
}
|
|
2516
|
+
return { extension };
|
|
2517
|
+
}
|
|
2518
|
+
async function writeAtomic(target, audio) {
|
|
2519
|
+
const temp = `${path.dirname(target)}/.${path.basename(target)}.${crypto.randomBytes(6).toString("hex")}.tmp`;
|
|
2520
|
+
try {
|
|
2521
|
+
await promises.writeFile(temp, audio, { flag: "wx", mode: 384 });
|
|
2522
|
+
await promises.rename(temp, target);
|
|
2523
|
+
} catch (err) {
|
|
2524
|
+
await promises.rm(temp, { force: true });
|
|
2525
|
+
throw err;
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
async function saveClip(projectRoot, outputDir, relativePath2, { audio, mimeType }) {
|
|
2529
|
+
const target = pathSafety.safePathJoin(projectRoot, relativePath2);
|
|
2530
|
+
try {
|
|
2531
|
+
await promises.mkdir(path.dirname(target), { recursive: true });
|
|
2532
|
+
const refused = checkPathScope(outputDir, projectRoot);
|
|
2533
|
+
if (refused !== null) return refused;
|
|
2534
|
+
await writeAtomic(target, audio);
|
|
2535
|
+
return json({ ok: true, path: relativePath2, mime_type: mimeType, bytes: audio.length });
|
|
2536
|
+
} catch (err) {
|
|
2537
|
+
return json({ ok: false, error: "write_failed", message: errorCode(err) });
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
function createTextToSpeechTool(opts) {
|
|
2541
|
+
const { synthesize, projectRoot } = opts;
|
|
2542
|
+
const outputDir = path.posix.normalize((opts.outputDir ?? "audio").replace(/\\/g, "/"));
|
|
2543
|
+
const maxTextChars = requirePositiveInteger(
|
|
2544
|
+
"maxTextChars",
|
|
2545
|
+
opts.maxTextChars ?? DEFAULT_MAX_TEXT_CHARS
|
|
2546
|
+
);
|
|
2547
|
+
const maxAudioBytes = requirePositiveInteger(
|
|
2548
|
+
"maxAudioBytes",
|
|
2549
|
+
opts.maxAudioBytes ?? DEFAULT_MAX_AUDIO_BYTES
|
|
2550
|
+
);
|
|
2551
|
+
return sdk.Tool.create({
|
|
2552
|
+
name: opts.name ?? "text_to_speech",
|
|
2553
|
+
description: opts.description ?? "Turn text into spoken audio and save it as a file in the project. Use when the user asks for speech, a voice reply or an audio clip. Returns { ok, path, mime_type, bytes } with the path relative to the project root, or { ok: false, error }. The speech provider is injected by the consumer.",
|
|
2554
|
+
inputSchema: zod.z.object({
|
|
2555
|
+
text: zod.z.string().min(1).describe("The text to speak."),
|
|
2556
|
+
filename: zod.z.string().optional().describe(
|
|
2557
|
+
"File name without extension (letters, digits, '.', '_', '-'). Default: derived from the text."
|
|
2558
|
+
)
|
|
2559
|
+
}),
|
|
2560
|
+
handler: async ({ text, filename }) => {
|
|
2561
|
+
if (text.length > maxTextChars) {
|
|
2562
|
+
return json({
|
|
2563
|
+
ok: false,
|
|
2564
|
+
error: "text_too_large",
|
|
2565
|
+
chars: text.length,
|
|
2566
|
+
max_chars: maxTextChars
|
|
2567
|
+
});
|
|
2568
|
+
}
|
|
2569
|
+
const stem = filename ?? defaultStem(text);
|
|
2570
|
+
const refused = refusePath(path.posix.join(outputDir, stem), stem, projectRoot);
|
|
2571
|
+
if (refused !== null) return refused;
|
|
2572
|
+
const synthesized = await synthesizeSafely(synthesize, text);
|
|
2573
|
+
if ("ok" in synthesized) return json(synthesized);
|
|
2574
|
+
const checked = checkAudio(synthesized, maxAudioBytes);
|
|
2575
|
+
if ("ok" in checked) return json(checked);
|
|
2576
|
+
const relativePath2 = path.posix.join(outputDir, `${stem}.${checked.extension}`);
|
|
2577
|
+
return saveClip(projectRoot, outputDir, relativePath2, synthesized);
|
|
2578
|
+
}
|
|
2579
|
+
});
|
|
2580
|
+
}
|
|
2464
2581
|
|
|
2465
2582
|
// src/todo-plan-nodes.ts
|
|
2466
2583
|
function todoItemsToPlanNodes(items) {
|
|
@@ -2663,7 +2780,7 @@ var MEDIA_TYPES = /* @__PURE__ */ new Map([
|
|
|
2663
2780
|
[".webp", "image/webp"]
|
|
2664
2781
|
]);
|
|
2665
2782
|
var DEFAULT_MAX_IMAGE_BYTES = 5 * 1024 * 1024;
|
|
2666
|
-
var
|
|
2783
|
+
var json2 = (result) => JSON.stringify(result);
|
|
2667
2784
|
function createViewImageTool(options) {
|
|
2668
2785
|
const { projectRoot } = options;
|
|
2669
2786
|
const maxBytes = options.maxBytes ?? DEFAULT_MAX_IMAGE_BYTES;
|
|
@@ -2677,11 +2794,11 @@ function createViewImageTool(options) {
|
|
|
2677
2794
|
const refused = checkPathScope(input.path, projectRoot);
|
|
2678
2795
|
if (refused !== null) return refused;
|
|
2679
2796
|
if (isForbiddenAtAnyDepth(input.path)) {
|
|
2680
|
-
return
|
|
2797
|
+
return json2({ ok: false, error: "path_traversal", path: input.path });
|
|
2681
2798
|
}
|
|
2682
2799
|
const mediaType = MEDIA_TYPES.get(path.extname(input.path).toLowerCase());
|
|
2683
2800
|
if (mediaType === void 0) {
|
|
2684
|
-
return
|
|
2801
|
+
return json2({
|
|
2685
2802
|
ok: false,
|
|
2686
2803
|
error: "unsupported_image_type",
|
|
2687
2804
|
path: input.path,
|
|
@@ -2690,8 +2807,8 @@ function createViewImageTool(options) {
|
|
|
2690
2807
|
}
|
|
2691
2808
|
const absolute = pathSafety.safePathJoin(projectRoot, input.path);
|
|
2692
2809
|
const outcome = readWithinBudget(absolute, maxBytes);
|
|
2693
|
-
if (!outcome.ok) return
|
|
2694
|
-
return
|
|
2810
|
+
if (!outcome.ok) return json2(failureFor(outcome, input.path, maxBytes));
|
|
2811
|
+
return json2({
|
|
2695
2812
|
ok: true,
|
|
2696
2813
|
path: input.path,
|
|
2697
2814
|
media_type: mediaType,
|
|
@@ -2888,8 +3005,8 @@ function createBraveWebSearchAdapter(opts = {}) {
|
|
|
2888
3005
|
headers: { "X-Subscription-Token": apiKey, Accept: "application/json" }
|
|
2889
3006
|
});
|
|
2890
3007
|
if (!res.ok) throw new Error(`brave_search_failed: HTTP ${res.status}`);
|
|
2891
|
-
const
|
|
2892
|
-
const results =
|
|
3008
|
+
const json3 = await res.json();
|
|
3009
|
+
const results = json3?.web?.results ?? [];
|
|
2893
3010
|
return results.map((r) => ({
|
|
2894
3011
|
title: String(r?.title ?? ""),
|
|
2895
3012
|
url: String(r?.url ?? ""),
|
|
@@ -3051,7 +3168,9 @@ async function isBinaryFile(absolutePath) {
|
|
|
3051
3168
|
|
|
3052
3169
|
exports.CatastrophicCommandError = CatastrophicCommandError;
|
|
3053
3170
|
exports.ContextMatchError = ContextMatchError;
|
|
3171
|
+
exports.DEFAULT_MAX_AUDIO_BYTES = DEFAULT_MAX_AUDIO_BYTES;
|
|
3054
3172
|
exports.DEFAULT_MAX_IMAGE_BYTES = DEFAULT_MAX_IMAGE_BYTES;
|
|
3173
|
+
exports.DEFAULT_MAX_TEXT_CHARS = DEFAULT_MAX_TEXT_CHARS;
|
|
3055
3174
|
exports.DEFAULT_TOOL_GUIDANCE = DEFAULT_TOOL_GUIDANCE;
|
|
3056
3175
|
exports.ReadTracker = ReadTracker;
|
|
3057
3176
|
exports.ReasoningTools = ReasoningTools;
|
|
@@ -3078,6 +3197,7 @@ exports.createRunVitestTool = createRunVitestTool;
|
|
|
3078
3197
|
exports.createSearchTextTool = createSearchTextTool;
|
|
3079
3198
|
exports.createSessionArtifactStore = createSessionArtifactStore;
|
|
3080
3199
|
exports.createShellTool = createShellTool;
|
|
3200
|
+
exports.createTextToSpeechTool = createTextToSpeechTool;
|
|
3081
3201
|
exports.createTodolistTool = createTodolistTool;
|
|
3082
3202
|
exports.createUpdatePlanTool = createUpdatePlanTool;
|
|
3083
3203
|
exports.createViewImageTool = createViewImageTool;
|