services-as-software
Version:
Primitives for building AI-powered services that operate as software
206 lines • 6.52 kB
JavaScript
/**
* Service implementation
*/
/**
* Create a service from a definition
*
* @example
* ```ts
* const service = Service({
* name: 'translation-service',
* version: '1.0.0',
* description: 'AI-powered translation service',
* pricing: {
* model: 'per-use',
* pricePerUnit: 0.01,
* currency: 'USD',
* },
* endpoints: [
* Endpoint({
* name: 'translate',
* method: 'POST',
* path: '/translate',
* input: {
* type: 'object',
* properties: {
* text: { type: 'string' },
* from: { type: 'string' },
* to: { type: 'string' },
* },
* required: ['text', 'to'],
* },
* handler: async (input) => {
* // Translation logic here
* return { translatedText: input.text }
* },
* }),
* ],
* })
* ```
*/
export function Service(definition) {
// Store endpoints by name for quick lookup
const endpointMap = new Map();
for (const endpoint of definition.endpoints) {
endpointMap.set(endpoint.name, endpoint);
}
// Store event handlers
const eventHandlers = new Map();
if (definition.events) {
for (const [event, handler] of Object.entries(definition.events)) {
eventHandlers.set(event, [handler]);
}
}
// Store scheduled tasks
const scheduledTasks = new Map();
if (definition.scheduled) {
for (const task of definition.scheduled) {
scheduledTasks.set(task.name, task);
}
}
// Create the service instance
const service = {
definition,
// Call an endpoint
async call(endpoint, input, context) {
const ep = endpointMap.get(endpoint);
if (!ep) {
throw new Error(`Endpoint not found: ${endpoint}`);
}
// Create context if not provided
const ctx = context || {
requestId: generateRequestId(),
entitlements: [],
};
// Track usage if tracker is available
if (ctx.usage && ctx.customerId) {
await ctx.usage.track({
customerId: ctx.customerId,
resource: endpoint,
quantity: 1,
timestamp: new Date(),
});
}
// Call the handler
return ep.handler(input, ctx);
},
// Ask a question
async ask(question, context) {
return service.call('ask', { question, context });
},
// Deliver results
async deliver(orderId, results) {
return service.call('deliver', { orderId, results });
},
// Execute a task
async do(action, input) {
return service.call('do', { action, input });
},
// Generate content
async generate(prompt, options) {
return service.call('generate', { prompt, options });
},
// Type checking/validation
async is(value, type) {
return service.call('is', { value, type });
},
// Send notification
async notify(notification) {
return service.call('notify', notification);
},
// Place an order
async order(product, quantity) {
return service.call('order', { product, quantity });
},
// Request a quote
async quote(product, quantity) {
return service.call('quote', { product, quantity });
},
// Subscribe to a plan
async subscribe(planId) {
return service.call('subscribe', { planId });
},
// Get entitlements
async entitlements() {
return service.call('entitlements', {});
},
// Get KPIs
async kpis() {
const result = {};
if (definition.kpis) {
for (const kpi of definition.kpis) {
result[kpi.id] = await kpi.calculate();
}
}
return result;
},
// Get OKRs
async okrs() {
if (!definition.okrs) {
return [];
}
// Calculate current values for key results
const okrs = await Promise.all(definition.okrs.map(async (okr) => {
const keyResults = await Promise.all(okr.keyResults.map(async (kr) => ({
...kr,
current: await kr.measure(),
})));
return { ...okr, keyResults };
}));
return okrs;
},
// Register event handler
on(event, handler) {
const handlers = eventHandlers.get(event) || [];
handlers.push({
event,
handler: handler,
});
eventHandlers.set(event, handlers);
},
// Schedule recurring task
every(schedule, handler) {
const taskName = `task-${scheduledTasks.size + 1}`;
scheduledTasks.set(taskName, {
name: taskName,
schedule,
handler: (_input, context) => handler(context),
enabled: true,
});
},
// Add queue processor
queue(name, handler) {
// Queue processing would typically integrate with a queue system
// For now, we add it as an event handler
service.on(`queue:${name}`, handler);
},
// Get service as RPC target
asRPC() {
// This would integrate with the RPC system from ai-functions
// For now, return a placeholder
return {
_type: 'rpc-target',
service: definition.name,
version: definition.version,
};
},
// Get service as API routes
asAPI() {
// This would generate HTTP/REST API routes
// For now, return a placeholder with route definitions
return definition.endpoints.map((ep) => ({
method: ep.method || 'POST',
path: ep.path || `/${ep.name}`,
handler: ep.handler,
}));
},
};
return service;
}
/**
* Generate a unique request ID
*/
function generateRequestId() {
return `req_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
}
//# sourceMappingURL=service.js.map