UNPKG

@stackmemoryai/stackmemory

Version:

Project-scoped memory for AI coding tools. Durable context across sessions with MCP integration, frames, smart retrieval, Claude Code skills, and automatic hooks.

198 lines (197 loc) 6.89 kB
import { fileURLToPath as __fileURLToPath } from 'url'; import { dirname as __pathDirname } from 'path'; const __filename = __fileURLToPath(import.meta.url); const __dirname = __pathDirname(__filename); import { z } from "zod"; import { logConfigInvalid } from "./security-logger.js"; const PromptOptionSchema = z.object({ key: z.string().max(10), label: z.string().max(200), action: z.string().max(500).optional() }); const PendingPromptSchema = z.object({ id: z.string().max(32), timestamp: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)), message: z.string().max(1e3), options: z.array(PromptOptionSchema).max(10), type: z.enum(["options", "yesno", "freeform"]), callback: z.string().max(500).optional(), expiresAt: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)) }); const NotifyOnSchema = z.object({ taskComplete: z.boolean(), reviewReady: z.boolean(), error: z.boolean(), custom: z.boolean(), contextSync: z.boolean().optional().default(true) }); const QuietHoursSchema = z.object({ enabled: z.boolean(), start: z.string().regex(/^\d{2}:\d{2}$/), end: z.string().regex(/^\d{2}:\d{2}$/) }); const SMSConfigSchema = z.object({ enabled: z.boolean(), channel: z.enum(["whatsapp", "sms"]), accountSid: z.string().max(100).optional(), authToken: z.string().max(100).optional(), smsFromNumber: z.string().max(20).optional(), smsToNumber: z.string().max(20).optional(), whatsappFromNumber: z.string().max(30).optional(), whatsappToNumber: z.string().max(30).optional(), fromNumber: z.string().max(20).optional(), toNumber: z.string().max(20).optional(), webhookUrl: z.string().url().max(500).optional(), notifyOn: NotifyOnSchema, quietHours: QuietHoursSchema.optional(), responseTimeout: z.number().int().min(30).max(3600), pendingPrompts: z.array(PendingPromptSchema).max(100) }); const PendingActionSchema = z.object({ id: z.string().max(32), promptId: z.string().max(32), response: z.string().max(1e3), action: z.string().max(500), timestamp: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)), status: z.enum(["pending", "running", "completed", "failed"]), result: z.string().max(1e4).optional(), error: z.string().max(1e3).optional() }); const ActionQueueSchema = z.object({ actions: z.array(PendingActionSchema).max(1e3), lastChecked: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)) }); const AutoBackgroundConfigSchema = z.object({ enabled: z.boolean(), timeoutMs: z.number().int().min(1e3).max(6e5), alwaysBackground: z.array(z.string().max(200)).max(100), neverBackground: z.array(z.string().max(200)).max(100), verbose: z.boolean().optional() }); const SyncOptionsSchema = z.object({ autoSyncOnClose: z.boolean(), minFrameDuration: z.number().int().min(0).max(3600), // 0 to 1 hour includeDecisions: z.boolean(), includeFiles: z.boolean(), includeTests: z.boolean(), maxDigestLength: z.number().int().min(100).max(1e3) // WhatsApp limit ~4096 chars }); const ScheduleConfigSchema = z.object({ type: z.enum(["daily", "hourly", "interval"]), time: z.string().regex(/^\d{2}:\d{2}$/).optional(), // "HH:MM" for daily intervalMinutes: z.number().int().min(5).max(1440).optional(), // 5 min to 24 hours includeInactive: z.boolean(), // Include when no activity quietHoursRespect: z.boolean() // Respect quiet hours setting }); const ScheduleSchema = z.object({ id: z.string().max(32), config: ScheduleConfigSchema, enabled: z.boolean(), lastRun: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)).optional(), nextRun: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)).optional(), createdAt: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)) }); const ScheduleStorageSchema = z.object({ schedules: z.array(ScheduleSchema).max(10), lastChecked: z.string().datetime({ offset: true }).or(z.string().regex(/^\d{4}-\d{2}-\d{2}T/)) }); const WhatsAppCommandSchema = z.object({ name: z.string().max(50), description: z.string().max(200), enabled: z.boolean(), action: z.string().max(500).optional(), // Safe action to execute requiresArg: z.boolean().optional(), argPattern: z.string().max(100).optional() // Regex pattern for arg validation }); const WhatsAppCommandsConfigSchema = z.object({ enabled: z.boolean(), commands: z.array(WhatsAppCommandSchema).max(50) }); const ModelProviderSchema = z.enum([ "anthropic", "qwen", "openai", "ollama", "custom" ]); const ModelConfigSchema = z.object({ provider: ModelProviderSchema, model: z.string().max(100), baseUrl: z.string().url().max(500).optional(), apiKeyEnv: z.string().max(100), headers: z.record(z.string().max(500)).optional(), params: z.record(z.unknown()).optional() }); const ModelRouterConfigSchema = z.object({ enabled: z.boolean(), defaultProvider: ModelProviderSchema, taskRouting: z.object({ plan: ModelProviderSchema.optional(), think: ModelProviderSchema.optional(), code: ModelProviderSchema.optional(), review: ModelProviderSchema.optional() }).optional().default({}), fallback: z.object({ enabled: z.boolean(), provider: ModelProviderSchema, onRateLimit: z.boolean(), onError: z.boolean(), onTimeout: z.boolean(), maxRetries: z.number().int().min(0).max(10), retryDelayMs: z.number().int().min(100).max(3e4) }), providers: z.object({ anthropic: ModelConfigSchema.optional(), qwen: ModelConfigSchema.optional(), openai: ModelConfigSchema.optional(), ollama: ModelConfigSchema.optional(), custom: ModelConfigSchema.optional() }).optional().default({}), thinkingMode: z.object({ enabled: z.boolean(), budget: z.number().int().min(1e3).max(1e5).optional(), temperature: z.number().min(0).max(2).optional(), topP: z.number().min(0).max(1).optional() }) }); function parseConfigSafe(schema, data, defaultValue, configName) { const result = schema.safeParse(data); if (result.success) { return result.data; } const errors = result.error.issues.map( (i) => `${i.path.join(".")}: ${i.message}` ); logConfigInvalid(configName, errors); console.error(`[hooks] Invalid ${configName} config:`, errors.join(", ")); return defaultValue; } export { ActionQueueSchema, AutoBackgroundConfigSchema, ModelConfigSchema, ModelProviderSchema, ModelRouterConfigSchema, NotifyOnSchema, PendingActionSchema, PendingPromptSchema, PromptOptionSchema, QuietHoursSchema, SMSConfigSchema, ScheduleConfigSchema, ScheduleSchema, ScheduleStorageSchema, SyncOptionsSchema, WhatsAppCommandSchema, WhatsAppCommandsConfigSchema, parseConfigSafe }; //# sourceMappingURL=schemas.js.map