export enum Apps { LINEAR = "LINEAR", SLACK = "SLACK", SOL = "SOL", GITHUB = "GITHUB", } export const AppNames = { [Apps.LINEAR]: "Linear", [Apps.SLACK]: "Slack", [Apps.SOL]: "Sol", [Apps.GITHUB]: "GitHub", } as const; // Define attribute structure export interface NodeAttribute { name: string; description: string; type?: "string" | "number" | "boolean" | "date" | "array"; required?: boolean; } // General node types that are common across all apps export const GENERAL_NODE_TYPES = { PERSON: { name: "Person", description: "Represents an individual, like a team member or contact", attributes: [ { name: "email", description: "The email address of the person", type: "string", }, { name: "role", description: "The role or position of the person", type: "string", }, ], }, APP: { name: "App", description: "A software application or service that's integrated", attributes: [], }, PLACE: { name: "Place", description: "A physical location like an office, meeting room, or city", attributes: [ { name: "address", description: "The address of the location", type: "string", }, { name: "coordinates", description: "Geographic coordinates of the location", type: "string", }, ], }, ORGANIZATION: { name: "Organization", description: "A company, team, or any formal group of people", attributes: [ { name: "industry", description: "The industry the organization operates in", type: "string", }, { name: "size", description: "The size of the organization", type: "string", }, ], }, EVENT: { name: "Event", description: "A meeting, deadline, or any time-based occurrence", attributes: [ { name: "startTime", description: "The start date and time of the event", type: "date", required: true, }, { name: "endTime", description: "The end date and time of the event", type: "date", }, { name: "location", description: "The location of the event", type: "string", }, ], }, ALIAS: { name: "Alias", description: "An alternative name or identifier for nouns and pronouns", attributes: [ { name: "originalName", description: "The original name this is an alias for", type: "string", }, { name: "context", description: "The context in which this alias is used", type: "string", }, ], }, FILE: { name: "File", description: "A document, image or other file shared in an app", attributes: [ { name: "fileId", description: "Unique identifier for the file", type: "string", required: true, }, { name: "source", description: "The source of the file", type: "string", required: true, }, ], }, } as const; // App-specific node types export const APP_NODE_TYPES = { [Apps.SOL]: { TASK: { name: "Sol Task", description: "An independent unit of work in Sol, such as a task, bug report, or feature request. Tasks can be associated with lists or linked as subtasks to other tasks.", attributes: [ { name: "taskId", description: "Unique identifier for the task", type: "string", required: true, }, ], }, LIST: { name: "Sol List", description: "A flexible container in Sol for organizing content such as tasks, text, or references. Lists are used for task tracking, information collections, or reference materials.", attributes: [ { name: "listId", description: "Unique identifier for the list", type: "string", required: true, }, ], }, PREFERENCE: { name: "Sol Preference", description: "A user-stated intent, setting, or configuration in Sol, such as preferred formats, notification settings, timezones, or other customizations. Preferences reflect how a user wants the system to behave.", attributes: [ { name: "key", description: "The preference key or name", type: "string", required: true, }, { name: "value", description: "The preference value", type: "string", required: true, }, ], }, AUTOMATION: { name: "Sol Automation", description: "A workflow or rule in Sol that automatically performs actions based on specific conditions or triggers, such as recurring tasks, reminders, or integrations with other systems.", attributes: [ { name: "automationId", description: "Unique identifier for the automation", type: "string", required: true, }, ], }, }, [Apps.LINEAR]: { ISSUE: { name: "Linear Issue", description: "A task, bug report, or feature request tracked in Linear", attributes: [ { name: "issueId", description: "Unique identifier for the issue", type: "string", required: true, }, ], }, PROJECT: { name: "Linear Project", description: "A collection of related issues and work items in Linear", attributes: [ { name: "projectId", description: "Unique identifier for the project", type: "string", required: true, }, ], }, CYCLE: { name: "Linear Cycle", description: "A time-boxed iteration of work in Linear", attributes: [ { name: "cycleId", description: "Unique identifier for the cycle", type: "string", required: true, }, ], }, TEAM: { name: "Linear Team", description: "A group of people working together in Linear", attributes: [ { name: "teamId", description: "Unique identifier for the team", type: "string", required: true, }, ], }, LABEL: { name: "Linear Label", description: "A tag used to categorize and organize issues in Linear", attributes: [ { name: "labelId", description: "Unique identifier for the label", type: "string", required: true, }, ], }, STATUS: { name: "Linear Status", description: "A status or state of a Linear issue (e.g., Todo, In Progress, Done, Completed)", attributes: [ { name: "statusName", description: "The name of the status", type: "string", required: true, }, ], }, }, [Apps.SLACK]: { CHANNEL: { name: "Slack Channel", description: "A dedicated space for team communication in Slack", attributes: [ { name: "channelId", description: "Unique identifier for the channel", type: "string", required: true, }, { name: "isPrivate", description: "Whether the channel is private", type: "boolean", }, ], }, THREAD: { name: "Slack Thread", description: "A focused conversation branch within a Slack channel", attributes: [ { name: "threadId", description: "Unique identifier for the thread", type: "string", required: true, }, { name: "parentMessageId", description: "ID of the parent message", type: "string", required: true, }, ], }, MESSAGE: { name: "Slack Message", description: "A single communication sent in a Slack channel or thread", attributes: [ { name: "messageId", description: "Unique identifier for the message", type: "string", required: true, }, ], }, REACTION: { name: "Slack Reaction", description: "An emoji response to a message in Slack", attributes: [ { name: "emoji", description: "The emoji used in the reaction", type: "string", required: true, }, ], }, }, [Apps.GITHUB]: { REPOSITORY: { name: "GitHub Repository", description: "A code repository hosted on GitHub", attributes: [ { name: "repoId", description: "Unique identifier for the repository", type: "string", required: true, }, { name: "name", description: "The name of the repository", type: "string", required: true, }, { name: "owner", description: "Owner (user or organization) of the repository", type: "string", required: true, }, ], }, ISSUE: { name: "GitHub Issue", description: "An issue created to track bugs, tasks, or feature requests", attributes: [ { name: "issueId", description: "Unique identifier for the issue", type: "string", required: true, }, ], }, PULL_REQUEST: { name: "GitHub Pull Request", description: "A pull request to propose changes to a repository", attributes: [ { name: "PR number", description: "Unique number for the pull request", type: "string", required: true, }, ], }, COMMIT: { name: "GitHub Commit", description: "A commit representing a set of changes in a repository", attributes: [ { name: "commitSha", description: "SHA hash of the commit", type: "string", required: true, }, ], }, BRANCH: { name: "GitHub Branch", description: "A branch in a GitHub repository", attributes: [ { name: "branchName", description: "Name of the branch", type: "string", required: true, }, ], }, }, } as const; /** * Returns both general node types and app-specific node types for given apps * @param apps Array of app names to get node types for * @returns Object containing general and app-specific node types */ export function getNodeTypes(apps: Array) { const appSpecificTypes = apps.reduce((acc, appName) => { return { ...acc, [appName]: APP_NODE_TYPES[appName], }; }, {}); return { general: GENERAL_NODE_TYPES, appSpecific: appSpecificTypes, }; } export function getNodeTypesString(apps: Array) { let nodeTypesString = ""; const generalTypes = Object.entries(GENERAL_NODE_TYPES) .map(([key, value]) => { return `- ${key}: "${value.description}"`; }) .join("\n"); nodeTypesString += `General Node Types:\n${generalTypes}\n\n`; const appSpecificTypes = apps.reduce((acc, appName) => { return { ...acc, [appName]: APP_NODE_TYPES[appName], }; }, {}); const appSpecificTypesString = Object.entries(appSpecificTypes) .map(([appName, types]) => { return `For ${appName}:\n${Object.entries(types as any) .map(([key, value]: any) => { return `- ${key}: "${value.description}"`; }) .join("\n")}\n\n`; }) .join("\n\n"); nodeTypesString += `App-specific Node Types:\n${appSpecificTypesString}`; return nodeTypesString; } export function getNodeAttributesString( apps: Array, ) {} /** * Check if a type is a preset type (from GENERAL_NODE_TYPES or APP_NODE_TYPES) */ export function isPresetType( type: string, apps: Array = [], ): boolean { // Check general types const generalTypes = Object.keys(GENERAL_NODE_TYPES).map( (key) => GENERAL_NODE_TYPES[key as keyof typeof GENERAL_NODE_TYPES].name, ); if (generalTypes.includes(type as any)) { return true; } // Check app-specific types for (const app of apps) { const appTypes = Object.keys(APP_NODE_TYPES[app] || {}).map( (key) => APP_NODE_TYPES[app][key as keyof (typeof APP_NODE_TYPES)[typeof app]] .name, ); if (appTypes.includes(type as any)) { return true; } } return false; } /** * Get all preset types for given apps */ export function getAllPresetTypes( apps: Array = [], ): string[] { const generalTypes = Object.keys(GENERAL_NODE_TYPES).map( (key) => GENERAL_NODE_TYPES[key as keyof typeof GENERAL_NODE_TYPES].name, ); const appTypes = apps.flatMap((app) => Object.keys(APP_NODE_TYPES[app] || {}).map( (key) => APP_NODE_TYPES[app][key as keyof (typeof APP_NODE_TYPES)[typeof app]] .name, ), ); return [...generalTypes, ...appTypes]; }