Edits history of script submission #22538 for ' Search and Execute Strale Capability (strale)'

  • bunnative
    One script reply has been approved by the moderators
    Ap­pro­ved
    //native
    
    // Search for a Strale capability and execute the best match.
    // Combines /v1/suggest (semantic search) with /v1/do (execution) in one step.
    // Useful in flows where you describe what data you need in natural language.
    //
    // Strale is the data layer for AI agents — every data source independently
    // quality-tested, scored, and audit-logged. https://strale.dev
    
    type Strale = {
      api_key: string;
      base_url?: string;
    };
    
    export async function main(
      strale: Strale,
      task: string,
      inputs: Record<string, unknown>,
      max_price_cents: number = 100,
      dry_run: boolean = false,
    ) {
      const baseUrl = strale.base_url ?? "https://api.strale.io";
    
      // Step 1: Search for matching capabilities
      const suggestResponse = await fetch(`${baseUrl}/v1/suggest`, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${strale.api_key}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ task, limit: 5 }),
      });
    
      if (!suggestResponse.ok) {
        const error = await suggestResponse.json().catch(() => ({ message: suggestResponse.statusText }));
        throw new Error(
          `Strale search error (${suggestResponse.status}): ${(error as any).error?.message ?? (error as any).message ?? "Unknown error"}`
        );
      }
    
      const suggestions = await suggestResponse.json() as {
        suggestions: Array<{
          slug: string;
          name: string;
          description: string;
          category: string;
          price_cents: number;
          quality_score?: number;
        }>;
      };
    
      if (!suggestions.suggestions?.length) {
        return {
          status: "no_match",
          task,
          message: "No matching capabilities found for this task.",
          suggestions: [],
        };
      }
    
      // Step 2: Pick best match within price budget
      const match = suggestions.suggestions.find((s) => s.price_cents <= max_price_cents);
      if (!match) {
        return {
          status: "over_budget",
          task,
          message: `Best match costs €${(suggestions.suggestions[0].price_cents / 100).toFixed(2)}, exceeds max €${(max_price_cents / 100).toFixed(2)}`,
          suggestions: suggestions.suggestions.map((s) => ({
            slug: s.slug,
            name: s.name,
            price: `€${(s.price_cents / 100).toFixed(2)}`,
          })),
        };
      }
    
      // Step 3: Execute the capability
      const doBody: Record<string, unknown> = {
        capability_slug: match.slug,
        inputs,
      };
      if (dry_run) {
        doBody.dry_run = true;
      }
    
      const doResponse = await fetch(`${baseUrl}/v1/do`, {
        method: "POST",
        headers: {
          "Authorization": `Bearer ${strale.api_key}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(doBody),
      });
    
      if (!doResponse.ok) {
        const error = await doResponse.json().catch(() => ({ message: doResponse.statusText }));
        throw new Error(
          `Strale execution error (${doResponse.status}): ${(error as any).error?.message ?? (error as any).message ?? "Unknown error"}`
        );
      }
    
      const result = await doResponse.json() as {
        transaction_id?: string;
        capability_slug: string;
        status: string;
        output?: Record<string, unknown>;
        provenance?: Record<string, unknown>;
        quality?: Record<string, unknown>;
        cost_cents?: number;
        wallet_balance_cents?: number;
        dry_run?: boolean;
      };
    
      return {
        status: "success",
        task,
        matched_capability: {
          slug: match.slug,
          name: match.name,
          description: match.description,
          quality_score: match.quality_score,
        },
        transaction_id: result.transaction_id,
        output: result.output,
        provenance: result.provenance,
        quality: result.quality,
        cost: result.cost_cents != null ? `€${(result.cost_cents / 100).toFixed(2)}` : undefined,
        wallet_balance_cents: result.wallet_balance_cents,
        dry_run: result.dry_run,
        other_matches: suggestions.suggestions
          .filter((s) => s.slug !== match.slug)
          .slice(0, 3)
          .map((s) => ({ slug: s.slug, name: s.name, price: `€${(s.price_cents / 100).toFixed(2)}` })),
      };
    }

    Submitted by hugo989 7 days ago