Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140import { tool } from "ai";import * as Effect from "effect/Effect";import { z } from "zod";import type { SkillResourceRead } from "../shared/skill-resources";import type { SkillIdentity } from "../shared/skill-management";import { skillName, type SkillListing } from "../shared/skills";import { agentCall, runAgent, type AgentFailure } from "./agent-io";import { skillCapability, skillIdentityOf } from "./skill-activity";import type { ToolActivityDescriptor } from "./tool-activity";
export interface SkillResourceRuntime { readSkillResource(value: { skill: SkillIdentity; path: string; }): Promise<SkillResourceRead | null>;}const request = z.strictObject({ name: skillName, path: z.string().min(1).max(240),});const unavailable = () => ({ ok: false as const, error: "Skill resource unavailable",});const bytes = (value: unknown) => new TextEncoder().encode(JSON.stringify(value)).byteLength;const MAX_RESULT_BYTES = 65_536;
// Bound the complete model result, including JSON escaping and provenance.// Keep native source bytes intact for other SDK consumers such as script runners.export function skillResourceResult({ skill, resource }: SkillResourceRead) { const metadata = skillCapability(skill, "read_skill_resource", resource.path); const output = { ok: true as const, id: metadata.id, skill: { source: skillIdentityOf(skill).source, name: skill.name, version: skill.version, fingerprint: skill.fingerprint, }, path: resource.path, kind: resource.kind, encoding: resource.encoding ?? "text", mimeType: resource.mimeType ?? null, content: resource.content, truncated: false, }; if (bytes(output) <= MAX_RESULT_BYTES) return output; output.truncated = true; const prefix = (length: number) => { if (output.encoding === "base64") length -= length % 4; else if (length > 0 && /[\uD800-\uDBFF]/.test(resource.content[length - 1])) length--; return resource.content.slice(0, length); }; let low = 0; // The shorter JSON boolean must not make an unchanged body look truncated. let high = resource.content.length - 1; while (low < high) { const middle = Math.ceil((low + high) / 2); output.content = prefix(middle); if (bytes(output) <= MAX_RESULT_BYTES) low = middle; else high = middle - 1; } output.content = prefix(low); return output;}
export class SkillResourceTools { constructor( private readonly parent: () => Effect.Effect< SkillResourceRuntime, AgentFailure >, private readonly catalog: () => SkillListing[], ) {}
readonly reader = tool({ description: "Read a resource from an enabled Skill by name and relative path. Activation lists available paths. Returns bounded content with Skill version and provenance; scripts are read as text and are never executed.", inputSchema: request, execute: (value, { abortSignal }) => runAgent( Effect.gen({ self: this }, function* () { const input = request.safeParse(value); if (!input.success) return unavailable(); const skill = this.catalog().find( (item) => item.name === input.data.name, ); if (!skill) return unavailable(); const expected = skillIdentityOf(skill); const loaded = yield* this.parent().pipe( Effect.flatMap((parent) => agentCall(() => parent.readSkillResource({ skill: expected, path: input.data.path, }), ), ), Effect.timeout("15 seconds"), Effect.catch(() => Effect.succeed(null)), ); return loaded ? skillResourceResult(loaded) : unavailable(); }), abortSignal, ), });
readonly activity: ToolActivityDescriptor = { kind: "other", label: "Read Skill resource", capability: (value) => { const input = request.safeParse(value); if (!input.success) return; const skill = this.catalog().find( (item) => item.name === input.data.name, ); return skill ? skillCapability(skill, "read_skill_resource", input.data.path) : undefined; }, outcome: (output) => output && typeof output === "object" && "ok" in output && output.ok === true ? "succeeded" : "failed", outputSummary: (output) => output && typeof output === "object" && "truncated" in output && output.truncated ? "Skill resource read; content truncated" : "Skill resource read", };}