
Product
Announcing Socket Fix 2.0
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
AI Captain is a powerful utility library that bridges window.ai's language model capabilities with LangChain-style patterns and abstractions. It provides a comprehensive set of tools for building robust AI-powered applications using window.ai's in-browser
[!TIP] ai.captain works well with ai.matey
A powerful, modular library that integrates with chrome's experimental window.ai API that adds much needed features atop the basic API.
npm install ai.captain
import ai from "ai.captain";
//...
import ai from "https://cdn.jsdelivr.net/npm/ai.captain@0.0.2/src/index.mjs";
//...
OR
import ai from "https://ga.jspm.io/npm:ai.matey@0.0.2/src/index.mjs";
//...
import {
createAICaptain,
TemplateSystem,
CompositionBuilder,
} from "ai.captain";
// Initialize components
const chain = await createAICaptain();
const templates = new TemplateSystem(chain.session); // Pass session to TemplateSystem
const composer = new CompositionBuilder(chain.session); // Pass session to CompositionBuilder
// Register template
templates.register(
"translator",
'You are a professional translator.\nTranslate "{text}" to {language}.',
{ text: "", language: "" }
);
// Create enhanced prompt function with caching
const enhancedPrompt = composer
.pipe(async (input) => {
// Apply template and get processed content
const content = await templates.apply("translator", input);
// Send to model using chain.session.prompt
const result = await chain.session.prompt(content);
return result.trim();
})
.build();
// Use the enhanced prompt
const translation = await enhancedPrompt({
text: "Hello world",
language: "Spanish",
});
console.log(translation); // Hola mundo
The Session
class manages interactions with window.ai:
import { createAICaptain } from "ai.captain";
// Create a new chain
const chain = await createAICaptain();
// Basic prompt
const response = await chain.session.prompt("Hello!");
// Stream response
const stream = await chain.session.promptStreaming("Tell me a story");
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(value);
}
} finally {
reader.releaseLock();
}
Create and manage message templates with validation:
import { createAICaptain } from "ai.captain";
// Initialize components
const chain = await createAICaptain();
const templates = new TemplateSystem(chain.session);
// Register a template
templates.register("assistant", "You are a helpful assistant.\n{query}", {
query: "",
});
// Use the template
const message = await templates.apply("assistant", {
query: "Tell me about Alice who is 25 years old",
});
// Send to model
const response = await chain.session.prompt(message);
Templates can inherit from other templates:
import { createAICaptain } from "ai.captain";
// Initialize components
const chain = await createAICaptain();
const templates = new TemplateSystem(chain.session);
// Register base template
templates.register("base", "You are a {role}.\n{query}", {
role: "",
query: "",
});
// Register specialized template that inherits from base
templates.inherit("translator", "base", {
role: "professional translator",
query: 'Translate "{text}" to {language}.',
});
// Use the inherited template
const message = await templates.apply("translator", {
text: "Hello world",
language: "Spanish",
});
// Send to model
const translation = await chain.session.prompt(message);
console.log(translation);
Efficient caching with composition:
import { createAICaptain, CompositionBuilder } from "ai.captain";
const chain = await createAICaptain();
const composer = new CompositionBuilder(chain.session);
const cachedPrompt = composer
.pipe(async (messages) => {
const result = await chain.session.prompt(messages);
return result.trim();
})
.build();
const response = await cachedPrompt("What is 2+2?");
console.log(response);
[!ERROR] Uncaught NotSupportedError: The model attempted to output text in an untested language, and was prevented from doing so.
Build complex chains of functionality:
import { createAICaptain, CompositionBuilder } from "ai.captain";
const chain = await createAICaptain();
const composer = new CompositionBuilder(chain.session);
const enhancedPrompt = composer
.pipe(async (input) => {
const result = await chain.session.prompt(input);
return result.trim();
})
.build();
const result = await enhancedPrompt("Hello!");
console.log(result);
See our Advanced Guide for detailed information about:
Check out our demo.html for a complete example of:
Create a new AI Captain instance with all features enabled.
function createAICaptain(options?: {
session?: {
temperature?: number;
};
}): Promise<AICaptain>;
The main class for interacting with window.ai's language models.
interface AICaptain {
session: Session;
capabilities: Capabilities;
templates: TemplateSystem;
composer: CompositionBuilder;
// ... other components
}
Manages interactions with window.ai's language models.
class Session {
constructor(session: Object);
/**
* Send a prompt to the model
* @throws {Error} When model output is in an untested language
* @throws {Error} For other model-related errors
*/
prompt(text: string, options?: { temperature?: number }): Promise<string>;
/**
* Send a prompt and receive a streaming response
* @returns A ReadableStream that must be consumed using a reader
*/
promptStreaming(
text: string,
options?: { temperature?: number }
): Promise<ReadableStream>;
/**
* Clean up resources
*/
destroy(): Promise<void>;
}
Creates and manages message templates with variable substitution.
class TemplateSystem {
constructor(session: Session);
/**
* Register a new template
*/
register(name: string, content: string, defaults?: Record<string, any>): void;
/**
* Create a new template that inherits from a parent template
* @throws {Error} When parent template is not found
*/
inherit(
name: string,
parentName: string,
defaults?: Record<string, any>
): void;
/**
* Apply a template with given variables
* @throws {Error} When template is not found
* @throws {Error} When required variables are missing
*/
apply(name: string, variables?: Record<string, any>): Promise<string>;
}
Advanced composition pattern builder for chaining operations.
class CompositionBuilder {
constructor(session: Session);
/**
* Add a processing step
*/
pipe(fn: Function): CompositionBuilder;
/**
* Add a conditional branch
*/
branch(
condition: Function,
ifTrue: Function,
ifFalse: Function
): CompositionBuilder;
/**
* Add parallel processing
*/
parallel(fns: Function[]): CompositionBuilder;
/**
* Build the composition
* @returns An async function that executes the composition
*/
build(): (input: any) => Promise<any>;
}
The library can throw several types of errors:
// Model output errors
Error: "The model attempted to output text in an untested language";
// Template errors
Error: "Template '[name]' not found";
Error: "Missing required parameter: [param]";
Error: "Parent template '[name]' not found";
// Session errors
Error: "window.ai API not available";
// JSON parsing errors
SyntaxError: "Unexpected token in JSON";
try {
const response = await chain.session.prompt(input);
console.log(response);
} catch (error) {
if (error.message?.includes("untested language")) {
console.error("Language not supported:", error.message);
} else {
console.error("Model error:", error.message);
}
}
try {
const result = await chain.session.prompt(jsonTemplate);
return JSON.parse(result.trim());
} catch (error) {
if (error instanceof SyntaxError) {
console.error("Failed to parse JSON response:", error);
return null;
}
throw error; // Re-throw other errors
}
const chain = await createAICaptain();
try {
// Use chain...
} finally {
await chain.session.destroy();
}
Please read our Contributing Guide for details on our code of conduct and the process for submitting pull requests.
This project is licensed under the MIT License - see the LICENSE file for details.
import { createAICaptain, TemplateSystem } from "ai.captain";
// Initialize components
const chain = await createAICaptain();
const templates = new TemplateSystem(chain.session);
// Register translation template
templates.register(
"translator",
'You are a professional translator.\nTranslate "{text}" to {language}.',
{ text: "", language: "" }
);
// Basic translation
const message = await templates.apply("translator", {
text: "Hello world",
language: "Spanish",
});
const result = await chain.session.prompt(message);
console.log(result);
// Streaming translation
const content = await templates.apply("translator", {
text: "Hello world",
language: "Spanish",
});
const stream = await chain.session.promptStreaming(content);
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(value);
}
} finally {
reader.releaseLock();
}
import {
createAICaptain,
TemplateSystem,
CompositionBuilder,
} from "ai.captain";
// Initialize components
const chain = await createAICaptain();
const templates = new TemplateSystem(chain.session);
const composer = new CompositionBuilder(chain.session);
// Register analysis template
templates.register(
"analyzer",
'You are an AI trained to analyze text sentiment and extract key points.\nAnalyze this text: {text}\nRespond with a JSON object containing "sentiment" (string), "confidence" (number between 0-1), and "key_points" (array of strings).',
{ text: "" }
);
// Create composition chain with error handling
const analyzeText = composer
.pipe(async (input) => {
try {
// Apply template
const content = await templates.apply("analyzer", { text: input });
// Get model response
const result = await chain.session.prompt(content);
// Parse JSON response
return JSON.parse(result.trim());
} catch (error) {
if (error instanceof SyntaxError) {
console.error("Failed to parse JSON response:", error);
return null;
}
if (error.message?.includes("untested language")) {
console.error("Language not supported:", error);
return null;
}
throw error; // Re-throw other errors
}
})
.pipe(async (data) => {
if (!data) return "Analysis failed";
return `Sentiment: ${data.sentiment} (${data.confidence * 100}% confident)\nKey points:\n${data.key_points.join("\n")}`;
})
.build();
// Use the composed function
try {
const result = await analyzeText(
"This product is amazing! The quality is outstanding and the price is reasonable."
);
console.log(result);
} catch (error) {
console.error("Analysis error:", error);
}
import { createAICaptain } from "ai.captain";
// Initialize chain
const chain = await createAICaptain();
// Function to stream with progress
async function streamWithProgress(prompt) {
const stream = await chain.session.promptStreaming(prompt);
const reader = stream.getReader();
let response = "";
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
response += value;
// Update progress (e.g., word count)
const words = response.split(/\s+/).length;
console.log(`Progress: ${words} words generated`);
}
return response;
} finally {
reader.releaseLock();
}
}
// Example usage
try {
console.log("Generating story...");
const story = await streamWithProgress(
"Write a short story about a magical forest"
);
console.log("\nFinal story:", story);
} catch (error) {
console.error("Error:", error);
}
FAQs
AI Captain is a powerful utility library that bridges window.ai's language model capabilities with LangChain-style patterns and abstractions. It provides a comprehensive set of tools for building robust AI-powered applications using window.ai's in-browser
We found that ai.captain demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.
Product
Socket’s new Tier 1 Reachability filters out up to 80% of irrelevant CVEs, so security teams can focus on the vulnerabilities that matter.